Skip to content

Commit cd05b56

Browse files
committed
Promote some warnings in BCMath to Errors
Also do a bit of refactoring at the same time. Closes GH-6105
1 parent f29bfc0 commit cd05b56

18 files changed

+99
-152
lines changed

ext/bcmath/bcmath.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -393,16 +393,8 @@ PHP_FUNCTION(bcpowmod)
393393
php_str2num(&second, ZSTR_VAL(right));
394394
php_str2num(&mod, ZSTR_VAL(modulus));
395395

396-
switch (bc_raisemod(first, second, mod, &result, scale)) {
397-
case 0:
398-
RETVAL_STR(bc_num2str_ex(result, scale));
399-
break;
400-
case -1:
401-
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
402-
break;
403-
case -2:
404-
zend_argument_value_error(2, "must be greater than 0");
405-
break;
396+
if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
397+
RETVAL_STR(bc_num2str_ex(result, scale));
406398
}
407399

408400
bc_free_num(&first);
@@ -481,7 +473,7 @@ PHP_FUNCTION(bcsqrt)
481473
if (bc_sqrt (&result, scale) != 0) {
482474
RETVAL_STR(bc_num2str_ex(result, scale));
483475
} else {
484-
zend_value_error("Square root of negative number");
476+
zend_argument_value_error(1, "must be greater than or equal to 0");
485477
}
486478

487479
bc_free_num(&result);

ext/bcmath/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE([bcmath],
55

66
if test "$PHP_BCMATH" != "no"; then
77
PHP_NEW_EXTENSION(bcmath, bcmath.c \
8-
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 \
8+
libbcmath/src/add.c libbcmath/src/div.c libbcmath/src/init.c libbcmath/src/neg.c libbcmath/src/raisemod.c libbcmath/src/sub.c \
99
libbcmath/src/compare.c libbcmath/src/divmod.c libbcmath/src/int2num.c libbcmath/src/num2long.c libbcmath/src/output.c libbcmath/src/recmul.c \
1010
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 \
1111
libbcmath/src/rmzero.c libbcmath/src/str2num.c,

ext/bcmath/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ARG_ENABLE("bcmath", "bc style precision math functions", "yes");
55
if (PHP_BCMATH == "yes") {
66
EXTENSION("bcmath", "bcmath.c", null, "-Iext/bcmath/libbcmath/src /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
77
ADD_SOURCES("ext/bcmath/libbcmath/src", "add.c div.c init.c neg.c \
8-
outofmem.c raisemod.c sub.c compare.c divmod.c int2num.c \
8+
raisemod.c sub.c compare.c divmod.c int2num.c \
99
num2long.c output.c recmul.c sqrt.c zero.c debug.c doaddsub.c \
1010
nearzero.c num2str.c raise.c rmzero.c str2num.c", "bcmath");
1111

ext/bcmath/libbcmath/src/bcmath.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
150150
int leading_zero));
151151

152152
/* Prototypes needed for external utility routines. */
153-
154-
_PROTOTYPE(void bc_out_of_memory, (void));
155-
156153
#define bc_new_num(length, scale) _bc_new_num_ex((length), (scale), 0)
157154
#define bc_free_num(num) _bc_free_num_ex((num), 0)
158155
#define bc_num2str(num) bc_num2str_ex((num), (num->n_scale))

ext/bcmath/libbcmath/src/init.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ _bc_new_num_ex (length, scale, persistent)
4444
int length, scale, persistent;
4545
{
4646
bc_num temp;
47-
/* PHP Change: add length check */
48-
if ((size_t)length+(size_t)scale > INT_MAX) {
49-
zend_error(E_ERROR, "Result too long, max is %d", INT_MAX);
50-
}
5147
/* PHP Change: malloc() -> pemalloc(), removed free_list code */
5248
temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent);
5349
temp->n_sign = PLUS;

ext/bcmath/libbcmath/src/num2str.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ zend_string
5555
str = zend_string_alloc(num->n_len + scale + signch + 1, 0);
5656
else
5757
str = zend_string_alloc(num->n_len + signch, 0);
58-
if (str == NULL) bc_out_of_memory();
5958

6059
/* The negative sign if needed. */
6160
sptr = ZSTR_VAL(str);

ext/bcmath/libbcmath/src/outofmem.c

Lines changed: 0 additions & 44 deletions
This file was deleted.

ext/bcmath/libbcmath/src/raise.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,18 @@ bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale)
5252
int calcscale;
5353
char neg;
5454

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

6268
/* Special case if exponent is a zero. */
6369
if (exponent == 0)

ext/bcmath/libbcmath/src/raisemod.c

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,41 @@
3636
#include <stdarg.h>
3737
#include "bcmath.h"
3838
#include "private.h"
39+
#include "zend_exceptions.h"
3940

40-
41-
/* Truncate a number to zero scale. To avoid sharing issues (refcount and
42-
shared n_value) the number is copied, this copy is truncated, and the
43-
original number is "freed". */
44-
45-
static void
46-
_bc_truncate (bc_num *num)
47-
{
48-
bc_num temp;
49-
50-
temp = bc_new_num ((*num)->n_len, 0);
51-
temp->n_sign = (*num)->n_sign;
52-
memcpy (temp->n_value, (*num)->n_value, (*num)->n_len);
53-
bc_free_num (num);
54-
*num = temp;
55-
}
56-
57-
58-
/* Raise BASE to the EXPO power, reduced modulo MOD. The result is
59-
placed in RESULT. If a EXPO is not an integer,
60-
only the integer part is used. */
61-
62-
int
63-
bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
41+
/* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. */
42+
zend_result bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
6443
{
6544
bc_num power, exponent, modulus, parity, temp;
6645
int rscale;
6746

68-
/* Check for correct numbers. */
69-
if (bc_is_zero(mod)) return -1;
70-
if (bc_is_neg(expo)) return -2;
47+
/* Check the base for scale digits. */
48+
if (base->n_scale != 0) {
49+
/* 1st argument from PHP_FUNCTION(bcpowmod) */
50+
zend_argument_value_error(1, "cannot have a fractional part");
51+
return FAILURE;
52+
}
53+
/* Check the exponent for scale digits. */
54+
if (expo->n_scale != 0) {
55+
/* 2nd argument from PHP_FUNCTION(bcpowmod) */
56+
zend_argument_value_error(2, "cannot have a fractional part");
57+
return FAILURE;
58+
}
59+
if (bc_is_neg(expo)) {
60+
zend_argument_value_error(2, "must be greater than or equal to 0");
61+
return FAILURE;
62+
}
63+
/* Check the modulus for scale digits. */
64+
if (mod->n_scale != 0) {
65+
/* 3rd argument from PHP_FUNCTION(bcpowmod) */
66+
zend_argument_value_error(3, "cannot have a fractional part");
67+
return FAILURE;
68+
}
69+
/* Modulus cannot be 0 */
70+
if (bc_is_zero(mod)) {
71+
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
72+
return FAILURE;
73+
}
7174

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

79-
/* Check the base for scale digits. */
80-
if (power->n_scale != 0)
81-
{
82-
php_error_docref (NULL, E_WARNING, "Non-zero scale in base");
83-
_bc_truncate (&power);
84-
}
85-
86-
/* Check the exponent for scale digits. */
87-
if (exponent->n_scale != 0)
88-
{
89-
php_error_docref (NULL, E_WARNING, "Non-zero scale in exponent");
90-
_bc_truncate (&exponent);
91-
}
92-
93-
/* Check the modulus for scale digits. */
94-
if (modulus->n_scale != 0)
95-
{
96-
php_error_docref (NULL, E_WARNING, "Non-zero scale in modulus");
97-
_bc_truncate (&modulus);
98-
}
99-
10082
/* Do the calculation. */
10183
rscale = MAX(scale, power->n_scale);
10284
if ( !bc_compare(modulus, BCG(_one_)) )
@@ -127,5 +109,5 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)
127109
bc_free_num (result);
128110
bc_free_num (&parity);
129111
*result = temp;
130-
return 0; /* Everything is OK. */
112+
return SUCCESS; /* Everything is OK. */
131113
}

ext/bcmath/tests/bcpow_error1.phpt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
66
?>
77
--FILE--
88
<?php
9-
var_dump(bcpow('1', '1.1', 2));
9+
try {
10+
var_dump(bcpow('1', '1.1', 2));
11+
} catch (\ValueError $e) {
12+
echo $e->getMessage() . \PHP_EOL;
13+
}
1014
?>
11-
--EXPECTF--
12-
Warning: bcpow(): Non-zero scale in exponent in %s on line %d
13-
string(4) "1.00"
15+
--EXPECT--
16+
bcpow(): Argument #2 ($exponent) cannot have a fractional part

ext/bcmath/tests/bcpow_error2.phpt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
66
?>
77
--FILE--
88
<?php
9-
var_dump(bcpow('0', '9223372036854775808', 2));
9+
try {
10+
var_dump(bcpow('0', '9223372036854775808', 2));
11+
} catch (\ValueError $e) {
12+
echo $e->getMessage() . \PHP_EOL;
13+
}
1014
?>
11-
--EXPECTF--
12-
Warning: bcpow(): Exponent too large in %s on line %d
13-
string(4) "1.00"
15+
--EXPECT--
16+
bcpow(): Argument #2 ($exponent) is too large

ext/bcmath/tests/bcpowmod.phpt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ bcpowmod() - Raise an arbitrary precision number to another, reduced by a specif
66
bcmath.scale=0
77
--FILE--
88
<?php
9-
echo bcpowmod("5", "2", "7") . "\n";
10-
echo bcpowmod("-2", "5", "7") . "\n";
11-
echo bcpowmod("10", "2147483648", "2047");
9+
var_dump(bcpowmod("5", "2", "7"));
10+
var_dump(bcpowmod("-2", "5", "7"));
11+
var_dump(bcpowmod("10", "2147483648", "2047"));
12+
var_dump(bcpowmod("10", "0", "2047"));
1213
?>
1314
--EXPECT--
14-
4
15-
-4
16-
790
15+
string(1) "4"
16+
string(2) "-4"
17+
string(3) "790"
18+
string(1) "1"

ext/bcmath/tests/bcpowmod_negative_exponent.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ try {
1313
}
1414
?>
1515
--EXPECT--
16-
bcpowmod(): Argument #2 ($exponent) must be greater than 0
16+
bcpowmod(): Argument #2 ($exponent) must be greater than or equal to 0

ext/bcmath/tests/bcpowmod_zero_modulus.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Gabriel Caruso ([email protected])
77
--FILE--
88
<?php
99
try {
10-
var_dump(bcpowmod('1', '-1', '0'));
10+
var_dump(bcpowmod('1', '1', '0'));
1111
} catch (DivisionByZeroError $ex) {
1212
echo $ex->getMessage(), PHP_EOL;
1313
}

ext/bcmath/tests/bcsqrt_error1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ try {
1414
}
1515
?>
1616
--EXPECT--
17-
Square root of negative number
17+
bcsqrt(): Argument #1 ($operand) must be greater than or equal to 0

ext/bcmath/tests/bug72093.phpt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ try {
1111
} catch (\ValueError $e) {
1212
echo $e->getMessage() . \PHP_EOL;
1313
}
14-
var_dump(bcpowmod(1, 1.2, 1, 1));
14+
try {
15+
var_dump(bcpowmod(1, 1.2, 1, 1));
16+
} catch (\ValueError $e) {
17+
echo $e->getMessage() . \PHP_EOL;
18+
}
1519
?>
16-
--EXPECTF--
20+
--EXPECT--
1721
bcpowmod(): Argument #4 ($scale) must be between 0 and 2147483647
18-
19-
Warning: bcpowmod(): Non-zero scale in exponent in %s on line %d
20-
string(3) "0.0"
22+
bcpowmod(): Argument #2 ($exponent) cannot have a fractional part

ext/bcmath/tests/bug75178.phpt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
66
?>
77
--FILE--
88
<?php
9-
var_dump(bcpowmod('4.1', '4', '3', 3));
10-
var_dump(bcpowmod('4', '4', '3.1', 3));
9+
try {
10+
var_dump(bcpowmod('4.1', '4', '3', 3));
11+
} catch (\ValueError $e) {
12+
echo $e->getMessage() . \PHP_EOL;
13+
}
14+
try {
15+
var_dump(bcpowmod('4', '4', '3.1', 3));
16+
} catch (\ValueError $e) {
17+
echo $e->getMessage() . \PHP_EOL;
18+
}
1119
?>
12-
--EXPECTF--
13-
Warning: bcpowmod(): Non-zero scale in base in %s on line %d
14-
string(5) "1.000"
15-
16-
Warning: bcpowmod(): Non-zero scale in modulus in %s on line %d
17-
string(5) "1.000"
20+
--EXPECT--
21+
bcpowmod(): Argument #1 ($base) cannot have a fractional part
22+
bcpowmod(): Argument #3 ($modulus) cannot have a fractional part

ext/bcmath/tests/bug78878.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
66
?>
77
--FILE--
88
<?php
9-
print @bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4));
9+
try {
10+
print bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4));
11+
} catch (\ValueError $e) {
12+
echo $e->getMessage() . \PHP_EOL;
13+
}
1014
?>
1115
--EXPECT--
12-
0
16+
bcpowmod(): Argument #3 ($modulus) cannot have a fractional part

0 commit comments

Comments
 (0)