Consider the following snippet within php_url_decode_ex() at ext/standard/url.c, called from PHPs urldecode() function:
|
else if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) |
|
&& isxdigit((int) *(data + 2))) { |
According to the C11 specification, isxdigit()'s (and all other ctype.h functions') only argument is of type int, and any value passed to it must be representable by unsigned char, i.e. 0-255.
§7.4:
The header <ctype.h> declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.
On platforms where plain char is signed (which is most), passing a char with a value <0 to int (or casting to int explicitly as in this case) will lead to signed integer extension, leading to a negative int value. Instead, the char value should be cast to unsigned char, so that no sign extension occurs.
Most platforms account for this common mistake. However, on NetBSD passing negative values to isxdigit() lead to an out-of-bounds read, leading to a segfault.
Consider the following snippet within
php_url_decode_ex()atext/standard/url.c, called from PHPsurldecode()function:php-src/ext/standard/url.c
Lines 592 to 593 in dcf6533
According to the C11 specification,
isxdigit()'s (and all otherctype.hfunctions') only argument is of typeint, and any value passed to it must be representable byunsigned char, i.e. 0-255.§7.4:
On platforms where plain
charis signed (which is most), passing acharwith a value <0 toint(or casting tointexplicitly as in this case) will lead to signed integer extension, leading to a negativeintvalue. Instead, thecharvalue should be cast tounsigned char, so that no sign extension occurs.Most platforms account for this common mistake. However, on NetBSD passing negative values to
isxdigit()lead to an out-of-bounds read, leading to a segfault.