diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 35ca450ceb78c..1ed870da3691d 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; 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) +}