diff --git a/NEWS b/NEWS index d26148877670..18334055feec 100644 --- a/NEWS +++ b/NEWS @@ -152,6 +152,9 @@ PHP NEWS . Fix NUL byte truncation in sqlite3 TEXT column handling. (ndossche) - Standard: + . Fixed bug GH-21738 (undefined behavior when passing non-ASCII bytes to + isxdigit() in url_decode, quoted_printable_decode and stripcslashes). + (lacatoire) . Fixed bug GH-19926 (reset internal pointer earlier while splicing array while COW violation flag is still set). (alexandre-daubois) . Added form feed (\f) in the default trimmed characters of trim(), rtrim() diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c index f4954a88f8fa..e82a31b786b8 100644 --- a/ext/standard/quot_print.c +++ b/ext/standard/quot_print.c @@ -210,8 +210,8 @@ PHP_FUNCTION(quoted_printable_decode) switch (str_in[i]) { case '=': if (str_in[i + 1] && str_in[i + 2] && - isxdigit((int) str_in[i + 1]) && - isxdigit((int) str_in[i + 2])) + isxdigit((unsigned char) str_in[i + 1]) && + isxdigit((unsigned char) str_in[i + 2])) { ZSTR_VAL(str_out)[j++] = (php_hex2int((int) str_in[i + 1]) << 4) + php_hex2int((int) str_in[i + 2]); diff --git a/ext/standard/string.c b/ext/standard/string.c index ef9e66ab53f8..21f25435f52a 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3760,9 +3760,9 @@ PHPAPI void php_stripcslashes(zend_string *str) case 'f': *target++='\f'; nlen--; break; case '\\': *target++='\\'; nlen--; break; case 'x': - if (source+1 < end && isxdigit((int)(*(source+1)))) { + if (source+1 < end && isxdigit((unsigned char)(*(source+1)))) { numtmp[0] = *++source; - if (source+1 < end && isxdigit((int)(*(source+1)))) { + if (source+1 < end && isxdigit((unsigned char)(*(source+1)))) { numtmp[1] = *++source; numtmp[2] = '\0'; nlen-=3; diff --git a/ext/standard/url.c b/ext/standard/url.c index 089dca315f43..4a35713fb37e 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -589,8 +589,8 @@ PHPAPI size_t php_url_decode_ex(char *dest, const char *src, size_t src_len) if (*data == '+') { *dest = ' '; } - else if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) - && isxdigit((int) *(data + 2))) { + else if (*data == '%' && src_len >= 2 && isxdigit((unsigned char) *(data + 1)) + && isxdigit((unsigned char) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; src_len -= 2; @@ -662,8 +662,8 @@ PHPAPI size_t php_raw_url_decode_ex(char *dest, const char *src, size_t src_len) const char *data = src; while (src_len--) { - if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) - && isxdigit((int) *(data + 2))) { + if (*data == '%' && src_len >= 2 && isxdigit((unsigned char) *(data + 1)) + && isxdigit((unsigned char) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; src_len -= 2;