A call to bccomp() with attacker-supplied inputs can lead to an out-of-bounds write to either stack or heap memory. The bug occurs in bc_str2num() when the scale truncates a number whose trailing zeros are subsequently trimmed.
|
/* |
|
* If set the scale manually and it is smaller than the automatically calculated scale, |
|
* adjust it to match the manual setting. |
|
*/ |
|
if (str_scale > scale && !auto_scale) { |
|
fractional_end -= str_scale - scale; |
|
str_scale = scale; |
|
|
|
/* |
|
* e.g. 123.0001 with scale 2 -> 123.00 |
|
* So, remove the trailing 0 again. |
|
*/ |
|
if (str_scale > 0) { |
|
const char *fractional_new_end = bc_skip_zero_reverse(fractional_end, fractional_ptr); |
|
str_scale -= fractional_end - fractional_new_end; /* fractional_end >= fractional_new_end */ |
|
} |
|
} |
str_scale later determines the number of digits after the decimal point in the resulting string.
|
*num = bc_new_num_nonzeroed(digits, str_scale); |
The string is later populated using bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end).
|
nptr = bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end); |
Note that we have shortened the allocated string (str_scale -= fractional_end - fractional_new_end;) but have not adjusted fractional_end itself. Consequently, bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end) will copy the original, untruncated string into a buffer that is too small, leading to an out-of-bounds write.
BCMath uses a small stack-allocated arena for numbers before falling back to heap allocation, enabling both stack and heap corruption, depending on where the buffer is allocated.
The patch adds fractional_end = fractional_new_end; after the zero truncation.
A call to
bccomp()with attacker-supplied inputs can lead to an out-of-bounds write to either stack or heap memory. The bug occurs inbc_str2num()when the scale truncates a number whose trailing zeros are subsequently trimmed.php-src/ext/bcmath/libbcmath/src/str2num.c
Lines 169 to 185 in a480965
str_scalelater determines the number of digits after the decimal point in the resulting string.php-src/ext/bcmath/libbcmath/src/str2num.c
Line 203 in a480965
The string is later populated using
bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end).php-src/ext/bcmath/libbcmath/src/str2num.c
Line 213 in a480965
Note that we have shortened the allocated string (
str_scale -= fractional_end - fractional_new_end;) but have not adjustedfractional_enditself. Consequently,bc_copy_and_toggle_bcd(nptr, fractional_ptr, fractional_end)will copy the original, untruncated string into a buffer that is too small, leading to an out-of-bounds write.BCMath uses a small stack-allocated arena for numbers before falling back to heap allocation, enabling both stack and heap corruption, depending on where the buffer is allocated.
The patch adds
fractional_end = fractional_new_end;after the zero truncation.