Skip to content

Bcmath warning to error promotions #6105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
14 changes: 3 additions & 11 deletions ext/bcmath/bcmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,16 +393,8 @@ PHP_FUNCTION(bcpowmod)
php_str2num(&second, ZSTR_VAL(right));
php_str2num(&mod, ZSTR_VAL(modulus));

switch (bc_raisemod(first, second, mod, &result, scale)) {
case 0:
RETVAL_STR(bc_num2str_ex(result, scale));
break;
case -1:
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
break;
case -2:
zend_argument_value_error(2, "must be greater than 0");
break;
if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
RETVAL_STR(bc_num2str_ex(result, scale));
}

bc_free_num(&first);
Expand Down Expand Up @@ -481,7 +473,7 @@ PHP_FUNCTION(bcsqrt)
if (bc_sqrt (&result, scale) != 0) {
RETVAL_STR(bc_num2str_ex(result, scale));
} else {
zend_value_error("Square root of negative number");
zend_argument_value_error(1, "must be greater than or equal to 0");
}

bc_free_num(&result);
Expand Down
2 changes: 1 addition & 1 deletion ext/bcmath/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PHP_ARG_ENABLE([bcmath],

if test "$PHP_BCMATH" != "no"; then
PHP_NEW_EXTENSION(bcmath, bcmath.c \
libbcmath/src/add.c libbcmath/src/div.c libbcmath/src/init.c libbcmath/src/neg.c libbcmath/src/outofmem.c libbcmath/src/raisemod.c libbcmath/src/sub.c \
libbcmath/src/add.c libbcmath/src/div.c libbcmath/src/init.c libbcmath/src/neg.c libbcmath/src/raisemod.c libbcmath/src/sub.c \
libbcmath/src/compare.c libbcmath/src/divmod.c libbcmath/src/int2num.c libbcmath/src/num2long.c libbcmath/src/output.c libbcmath/src/recmul.c \
libbcmath/src/sqrt.c libbcmath/src/zero.c libbcmath/src/debug.c libbcmath/src/doaddsub.c libbcmath/src/nearzero.c libbcmath/src/num2str.c libbcmath/src/raise.c \
libbcmath/src/rmzero.c libbcmath/src/str2num.c,
Expand Down
2 changes: 1 addition & 1 deletion ext/bcmath/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ARG_ENABLE("bcmath", "bc style precision math functions", "yes");
if (PHP_BCMATH == "yes") {
EXTENSION("bcmath", "bcmath.c", null, "-Iext/bcmath/libbcmath/src /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
ADD_SOURCES("ext/bcmath/libbcmath/src", "add.c div.c init.c neg.c \
outofmem.c raisemod.c sub.c compare.c divmod.c int2num.c \
raisemod.c sub.c compare.c divmod.c int2num.c \
num2long.c output.c recmul.c sqrt.c zero.c debug.c doaddsub.c \
nearzero.c num2str.c raise.c rmzero.c str2num.c", "bcmath");

Expand Down
3 changes: 0 additions & 3 deletions ext/bcmath/libbcmath/src/bcmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@ _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
int leading_zero));

/* Prototypes needed for external utility routines. */

_PROTOTYPE(void bc_out_of_memory, (void));

#define bc_new_num(length, scale) _bc_new_num_ex((length), (scale), 0)
#define bc_free_num(num) _bc_free_num_ex((num), 0)
#define bc_num2str(num) bc_num2str_ex((num), (num->n_scale))
Expand Down
4 changes: 0 additions & 4 deletions ext/bcmath/libbcmath/src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ _bc_new_num_ex (length, scale, persistent)
int length, scale, persistent;
{
bc_num temp;
/* PHP Change: add length check */
if ((size_t)length+(size_t)scale > INT_MAX) {
zend_error(E_ERROR, "Result too long, max is %d", INT_MAX);
}
/* PHP Change: malloc() -> pemalloc(), removed free_list code */
temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent);
temp->n_sign = PLUS;
Expand Down
1 change: 0 additions & 1 deletion ext/bcmath/libbcmath/src/num2str.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ zend_string
str = zend_string_alloc(num->n_len + scale + signch + 1, 0);
else
str = zend_string_alloc(num->n_len + signch, 0);
if (str == NULL) bc_out_of_memory();

/* The negative sign if needed. */
sptr = ZSTR_VAL(str);
Expand Down
44 changes: 0 additions & 44 deletions ext/bcmath/libbcmath/src/outofmem.c

This file was deleted.

18 changes: 12 additions & 6 deletions ext/bcmath/libbcmath/src/raise.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,18 @@ bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale)
int calcscale;
char neg;

/* Check the exponent for scale digits and convert to a long. */
if (num2->n_scale != 0)
php_error_docref (NULL, E_WARNING, "Non-zero scale in exponent");
exponent = bc_num2long (num2);
if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
php_error_docref (NULL, E_WARNING, "Exponent too large");
/* Check the exponent for scale digits and convert to a long. */
if (num2->n_scale != 0) {
/* 2nd argument from PHP_FUNCTION(bcpow) */
zend_argument_value_error(2, "cannot have a fractional part");
return;
}
exponent = bc_num2long (num2);
if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) {
/* 2nd argument from PHP_FUNCTION(bcpow) */
zend_argument_value_error(2, "is too large");
return;
}

/* Special case if exponent is a zero. */
if (exponent == 0)
Expand Down
80 changes: 31 additions & 49 deletions ext/bcmath/libbcmath/src/raisemod.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,41 @@
#include <stdarg.h>
#include "bcmath.h"
#include "private.h"
#include "zend_exceptions.h"


/* Truncate a number to zero scale. To avoid sharing issues (refcount and
shared n_value) the number is copied, this copy is truncated, and the
original number is "freed". */

static void
_bc_truncate (bc_num *num)
{
bc_num temp;

temp = bc_new_num ((*num)->n_len, 0);
temp->n_sign = (*num)->n_sign;
memcpy (temp->n_value, (*num)->n_value, (*num)->n_len);
bc_free_num (num);
*num = temp;
}


/* Raise BASE to the EXPO power, reduced modulo MOD. The result is
placed in RESULT. If a EXPO is not an integer,
only the integer part is used. */

int
bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
/* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. */
zend_result bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
{
bc_num power, exponent, modulus, parity, temp;
int rscale;

/* Check for correct numbers. */
if (bc_is_zero(mod)) return -1;
if (bc_is_neg(expo)) return -2;
/* Check the base for scale digits. */
if (base->n_scale != 0) {
/* 1st argument from PHP_FUNCTION(bcpowmod) */
zend_argument_value_error(1, "cannot have a fractional part");
return FAILURE;
}
/* Check the exponent for scale digits. */
if (expo->n_scale != 0) {
/* 2nd argument from PHP_FUNCTION(bcpowmod) */
zend_argument_value_error(2, "cannot have a fractional part");
return FAILURE;
}
if (bc_is_neg(expo)) {
zend_argument_value_error(2, "must be greater than or equal to 0");
return FAILURE;
}
/* Check the modulus for scale digits. */
if (mod->n_scale != 0) {
/* 3rd argument from PHP_FUNCTION(bcpowmod) */
zend_argument_value_error(3, "cannot have a fractional part");
return FAILURE;
}
/* Modulus cannot be 0 */
if (bc_is_zero(mod)) {
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
return FAILURE;
}

/* Set initial values. */
power = bc_copy_num (base);
Expand All @@ -76,27 +79,6 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
temp = bc_copy_num (BCG(_one_));
bc_init_num(&parity);

/* Check the base for scale digits. */
if (power->n_scale != 0)
{
php_error_docref (NULL, E_WARNING, "Non-zero scale in base");
_bc_truncate (&power);
}

/* Check the exponent for scale digits. */
if (exponent->n_scale != 0)
{
php_error_docref (NULL, E_WARNING, "Non-zero scale in exponent");
_bc_truncate (&exponent);
}

/* Check the modulus for scale digits. */
if (modulus->n_scale != 0)
{
php_error_docref (NULL, E_WARNING, "Non-zero scale in modulus");
_bc_truncate (&modulus);
}

/* Do the calculation. */
rscale = MAX(scale, power->n_scale);
if ( !bc_compare(modulus, BCG(_one_)) )
Expand Down Expand Up @@ -127,5 +109,5 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
bc_free_num (result);
bc_free_num (&parity);
*result = temp;
return 0; /* Everything is OK. */
return SUCCESS; /* Everything is OK. */
}
11 changes: 7 additions & 4 deletions ext/bcmath/tests/bcpow_error1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
?>
--FILE--
<?php
var_dump(bcpow('1', '1.1', 2));
try {
var_dump(bcpow('1', '1.1', 2));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECTF--
Warning: bcpow(): Non-zero scale in exponent in %s on line %d
string(4) "1.00"
--EXPECT--
bcpow(): Argument #2 ($exponent) cannot have a fractional part
11 changes: 7 additions & 4 deletions ext/bcmath/tests/bcpow_error2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
?>
--FILE--
<?php
var_dump(bcpow('0', '9223372036854775808', 2));
try {
var_dump(bcpow('0', '9223372036854775808', 2));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECTF--
Warning: bcpow(): Exponent too large in %s on line %d
string(4) "1.00"
--EXPECT--
bcpow(): Argument #2 ($exponent) is too large
14 changes: 8 additions & 6 deletions ext/bcmath/tests/bcpowmod.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ bcpowmod() - Raise an arbitrary precision number to another, reduced by a specif
bcmath.scale=0
--FILE--
<?php
echo bcpowmod("5", "2", "7") . "\n";
echo bcpowmod("-2", "5", "7") . "\n";
echo bcpowmod("10", "2147483648", "2047");
var_dump(bcpowmod("5", "2", "7"));
var_dump(bcpowmod("-2", "5", "7"));
var_dump(bcpowmod("10", "2147483648", "2047"));
var_dump(bcpowmod("10", "0", "2047"));
?>
--EXPECT--
4
-4
790
string(1) "4"
string(2) "-4"
string(3) "790"
string(1) "1"
2 changes: 1 addition & 1 deletion ext/bcmath/tests/bcpowmod_negative_exponent.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ try {
}
?>
--EXPECT--
bcpowmod(): Argument #2 ($exponent) must be greater than 0
bcpowmod(): Argument #2 ($exponent) must be greater than or equal to 0
2 changes: 1 addition & 1 deletion ext/bcmath/tests/bcpowmod_zero_modulus.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Gabriel Caruso ([email protected])
--FILE--
<?php
try {
var_dump(bcpowmod('1', '-1', '0'));
var_dump(bcpowmod('1', '1', '0'));
} catch (DivisionByZeroError $ex) {
echo $ex->getMessage(), PHP_EOL;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/bcmath/tests/bcsqrt_error1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ try {
}
?>
--EXPECT--
Square root of negative number
bcsqrt(): Argument #1 ($operand) must be greater than or equal to 0
12 changes: 7 additions & 5 deletions ext/bcmath/tests/bug72093.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ try {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump(bcpowmod(1, 1.2, 1, 1));
try {
var_dump(bcpowmod(1, 1.2, 1, 1));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECTF--
--EXPECT--
bcpowmod(): Argument #4 ($scale) must be between 0 and 2147483647

Warning: bcpowmod(): Non-zero scale in exponent in %s on line %d
string(3) "0.0"
bcpowmod(): Argument #2 ($exponent) cannot have a fractional part
21 changes: 13 additions & 8 deletions ext/bcmath/tests/bug75178.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
?>
--FILE--
<?php
var_dump(bcpowmod('4.1', '4', '3', 3));
var_dump(bcpowmod('4', '4', '3.1', 3));
try {
var_dump(bcpowmod('4.1', '4', '3', 3));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
var_dump(bcpowmod('4', '4', '3.1', 3));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECTF--
Warning: bcpowmod(): Non-zero scale in base in %s on line %d
string(5) "1.000"

Warning: bcpowmod(): Non-zero scale in modulus in %s on line %d
string(5) "1.000"
--EXPECT--
bcpowmod(): Argument #1 ($base) cannot have a fractional part
bcpowmod(): Argument #3 ($modulus) cannot have a fractional part
8 changes: 6 additions & 2 deletions ext/bcmath/tests/bug78878.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
?>
--FILE--
<?php
print @bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4));
try {
print bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECT--
0
bcpowmod(): Argument #3 ($modulus) cannot have a fractional part