diff --git a/NEWS b/NEWS index 26bbf705270d1..17884e5774836 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - BcMath: . Fixed bug GH-16265 (Added early return case when result is 0) (Saki Takamachi). + . Fixed bug GH-16262 (Fixed a bug where size_t underflows) (Saki Takamachi). - Core: . Fixed bug GH-16574 (Incorrect error "undefined method" messages). diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index a9c001afcc94b..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; 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) +}