diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 35ca450ceb78c..9c8344fe771a8 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -434,7 +434,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) numerator_bottom_extension -= scale_diff; } else { numerator_bottom_extension = 0; - numeratorend -= scale_diff - numerator_bottom_extension; + numeratorend -= scale_diff > numerator_top_extension ? scale_diff - numerator_top_extension : 0; } } else { numerator_bottom_extension += scale - numerator_scale; @@ -444,6 +444,11 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) /* Length of numerator data that can be read */ size_t numerator_readable_len = numeratorend - numeratorptr + 1; + if (divisor_len > numerator_readable_len + numerator_bottom_extension) { + *quot = bc_copy_num(BCG(_zero_)); + return true; + } + /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ if (divisor_len == 1 && *divisorptr == 1) { if (numerator_len == 0) { diff --git a/ext/bcmath/tests/gh16262.phpt b/ext/bcmath/tests/gh16262.phpt new file mode 100644 index 0000000000000..e932bae2301ab --- /dev/null +++ b/ext/bcmath/tests/gh16262.phpt @@ -0,0 +1,158 @@ +--TEST-- +GH-16262 Stack buffer overflow in ext/bcmath/libbcmath/src/div.c:459 +--EXTENSIONS-- +bcmath +--INI-- +bcmath.scale=0 +--FILE-- +div('1000', $scale), + ); + echo "1 / 2000:\n"; + var_dump( + bcdiv('1', '2000', $scale), + (new BcMath\Number('1'))->div('2000', $scale), + ); + echo "\n"; +} +?> +--EXPECT-- +========== scale: null ========== +1 / 1000: +string(1) "0" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(5) "0.001" + ["scale"]=> + int(3) +} +1 / 2000: +string(1) "0" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(6) "0.0005" + ["scale"]=> + int(4) +} + +========== scale: 0 ========== +1 / 1000: +string(1) "0" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(1) "0" + ["scale"]=> + int(0) +} +1 / 2000: +string(1) "0" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(1) "0" + ["scale"]=> + int(0) +} + +========== scale: 1 ========== +1 / 1000: +string(3) "0.0" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(3) "0.0" + ["scale"]=> + int(1) +} +1 / 2000: +string(3) "0.0" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(3) "0.0" + ["scale"]=> + int(1) +} + +========== scale: 2 ========== +1 / 1000: +string(4) "0.00" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(4) "0.00" + ["scale"]=> + int(2) +} +1 / 2000: +string(4) "0.00" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(4) "0.00" + ["scale"]=> + int(2) +} + +========== scale: 3 ========== +1 / 1000: +string(5) "0.001" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(5) "0.001" + ["scale"]=> + int(3) +} +1 / 2000: +string(5) "0.000" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(5) "0.000" + ["scale"]=> + int(3) +} + +========== scale: 4 ========== +1 / 1000: +string(6) "0.0010" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(6) "0.0010" + ["scale"]=> + int(4) +} +1 / 2000: +string(6) "0.0005" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(6) "0.0005" + ["scale"]=> + int(4) +} + +========== scale: 5 ========== +1 / 1000: +string(7) "0.00100" +object(BcMath\Number)#2 (2) { + ["value"]=> + string(7) "0.00100" + ["scale"]=> + int(5) +} +1 / 2000: +string(7) "0.00050" +object(BcMath\Number)#1 (2) { + ["value"]=> + string(7) "0.00050" + ["scale"]=> + int(5) +} diff --git a/ext/bcmath/tests/gh16265.phpt b/ext/bcmath/tests/gh16265.phpt new file mode 100644 index 0000000000000..bc562d81df1ad --- /dev/null +++ b/ext/bcmath/tests/gh16265.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-16265 Segmentation fault (index oob) in ext/bcmath/libbcmath/src/convert.c:155 +--EXTENSIONS-- +bcmath +--INI-- +bcmath.scale=0 +--FILE-- + +--EXPECT-- +0.000000000