UBSan: Avoid unsigned integer overflow in utf8_{,un}escape()

Split the if/while loop condition into two independent steps so that
in_size-- happens only in the case in_size is nonzero. This gets rid of
unnecessary UBSan warnings.

common.c:1087:16: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
common.c:1076:16: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
common.c:1119:16: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-02-23 16:03:47 +02:00
parent cc4cdefc7f
commit fed7d8fcba

View file

@ -1,6 +1,6 @@
/* /*
* wpa_supplicant/hostapd / common helper functions, etc. * wpa_supplicant/hostapd / common helper functions, etc.
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -1073,7 +1073,8 @@ size_t utf8_unescape(const char *inp, size_t in_size,
in_size--; in_size--;
} }
while (in_size--) { while (in_size) {
in_size--;
if (res_size >= out_size) if (res_size >= out_size)
return 0; return 0;
@ -1084,8 +1085,9 @@ size_t utf8_unescape(const char *inp, size_t in_size,
return res_size; return res_size;
case '\\': case '\\':
if (!in_size--) if (!in_size)
return 0; return 0;
in_size--;
inp++; inp++;
/* fall through */ /* fall through */
@ -1116,7 +1118,8 @@ size_t utf8_escape(const char *inp, size_t in_size,
if (!in_size) if (!in_size)
in_size = os_strlen(inp); in_size = os_strlen(inp);
while (in_size--) { while (in_size) {
in_size--;
if (res_size++ >= out_size) if (res_size++ >= out_size)
return 0; return 0;