diff options
Diffstat (limited to 'ext/bcmath')
-rw-r--r-- | ext/bcmath/bcmath.c | 17 | ||||
-rw-r--r-- | ext/bcmath/config.m4 | 2 | ||||
-rw-r--r-- | ext/bcmath/config.w32 | 2 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/bcmath.h | 2 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/raise.c | 4 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/raisemod.c | 48 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/rt.c | 65 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/str2num.c | 3 | ||||
-rw-r--r-- | ext/bcmath/tests/bcpow_error1.phpt | 15 | ||||
-rw-r--r-- | ext/bcmath/tests/bcpow_error2.phpt | 15 | ||||
-rw-r--r-- | ext/bcmath/tests/bcscale_variation003.phpt | 18 | ||||
-rw-r--r-- | ext/bcmath/tests/bug46781.phpt | 16 | ||||
-rw-r--r-- | ext/bcmath/tests/bug72093-win32.phpt | 18 | ||||
-rw-r--r-- | ext/bcmath/tests/bug72093.phpt | 6 | ||||
-rw-r--r-- | ext/bcmath/tests/bug75178.phpt | 19 |
15 files changed, 140 insertions, 110 deletions
diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index dc51f92b55..1186241620 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -89,7 +89,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_bccomp, 0, 0, 2) ZEND_ARG_INFO(0, scale) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_bcscale, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_bcscale, 0, 0, 0) ZEND_ARG_INFO(0, scale) ZEND_END_ARG_INFO() @@ -530,19 +530,24 @@ PHP_FUNCTION(bccomp) } /* }}} */ -/* {{{ proto bool bcscale(int scale) +/* {{{ proto int bcscale([int scale]) Sets default scale parameter for all bc math functions */ PHP_FUNCTION(bcscale) { - zend_long new_scale; + zend_long old_scale, new_scale; - ZEND_PARSE_PARAMETERS_START(1, 1) + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL Z_PARAM_LONG(new_scale) ZEND_PARSE_PARAMETERS_END(); - BCG(bc_precision) = ((int)new_scale < 0) ? 0 : new_scale; + old_scale = BCG(bc_precision); + + if (ZEND_NUM_ARGS() == 1) { + BCG(bc_precision) = ((int)new_scale < 0) ? 0 : new_scale; + } - RETURN_TRUE; + RETURN_LONG(old_scale); } /* }}} */ diff --git a/ext/bcmath/config.m4 b/ext/bcmath/config.m4 index bc126454b4..85c535d0f5 100644 --- a/ext/bcmath/config.m4 +++ b/ext/bcmath/config.m4 @@ -7,7 +7,7 @@ PHP_ARG_ENABLE(bcmath, whether to enable bc style precision math functions, 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/rt.c libbcmath/src/sub.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/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, diff --git a/ext/bcmath/config.w32 b/ext/bcmath/config.w32 index 3973c10cbf..f79df604b8 100644 --- a/ext/bcmath/config.w32 +++ b/ext/bcmath/config.w32 @@ -6,7 +6,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 rt.c sub.c compare.c divmod.c int2num.c \ + outofmem.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"); diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index 08c548063e..78868edcb3 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -151,8 +151,6 @@ _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int), /* Prototypes needed for external utility routines. */ -_PROTOTYPE(void bc_rt_warn, (char *mesg ,...)); -_PROTOTYPE(void bc_rt_error, (char *mesg ,...)); _PROTOTYPE(void bc_out_of_memory, (void)); #define bc_new_num(length, scale) _bc_new_num_ex((length), (scale), 0) diff --git a/ext/bcmath/libbcmath/src/raise.c b/ext/bcmath/libbcmath/src/raise.c index c625d4e526..c7838be597 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -55,10 +55,10 @@ bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale) /* Check the exponent for scale digits and convert to a long. */ if (num2->n_scale != 0) - bc_rt_warn ("non-zero scale in exponent"); + 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)) - bc_rt_error ("exponent too large in raise"); + php_error_docref (NULL, E_WARNING, "exponent too large"); /* Special case if exponent is a zero. */ if (exponent == 0) diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index 84a7321ea7..a3154b55cd 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -38,6 +38,24 @@ #include "bcmath.h" #include "private.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. */ @@ -45,7 +63,7 @@ int bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) { - bc_num power, exponent, parity, temp; + bc_num power, exponent, modulus, parity, temp; int rscale; /* Check for correct numbers. */ @@ -55,27 +73,34 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); + modulus = bc_copy_num (mod); temp = bc_copy_num (BCG(_one_)); bc_init_num(&parity); /* Check the base for scale digits. */ - if (base->n_scale != 0) - bc_rt_warn ("non-zero scale in base"); + 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) { - bc_rt_warn ("non-zero scale in exponent"); - bc_divide (exponent, BCG(_one_), &exponent, 0); /*truncate */ + php_error_docref (NULL, E_WARNING, "non-zero scale in exponent"); + _bc_truncate (&exponent); } /* Check the modulus for scale digits. */ - if (mod->n_scale != 0) - bc_rt_warn ("non-zero scale in modulus"); + 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, base->n_scale); - if ( !bc_compare(mod, BCG(_one_)) ) + rscale = MAX(scale, power->n_scale); + if ( !bc_compare(modulus, BCG(_one_)) ) { temp = bc_new_num (1, scale); } @@ -87,17 +112,18 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) if ( !bc_is_zero(parity) ) { bc_multiply (temp, power, &temp, rscale); - (void) bc_modulo (temp, mod, &temp, scale); + (void) bc_modulo (temp, modulus, &temp, scale); } bc_multiply (power, power, &power, rscale); - (void) bc_modulo (power, mod, &power, scale); + (void) bc_modulo (power, modulus, &power, scale); } } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); + bc_free_num (&modulus); bc_free_num (result); bc_free_num (&parity); *result = temp; diff --git a/ext/bcmath/libbcmath/src/rt.c b/ext/bcmath/libbcmath/src/rt.c deleted file mode 100644 index 5f4d46527c..0000000000 --- a/ext/bcmath/libbcmath/src/rt.c +++ /dev/null @@ -1,65 +0,0 @@ -/* rt.c: bcmath library file. */ -/* - Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc. - Copyright (C) 2000 Philip A. Nelson - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. (COPYING.LIB) - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to: - - The Free Software Foundation, Inc. - 59 Temple Place, Suite 330 - Boston, MA 02111-1307 USA. - - You may contact the author by: - e-mail: philnelson@acm.org - us-mail: Philip A. Nelson - Computer Science Department, 9062 - Western Washington University - Bellingham, WA 98226-9062 - -*************************************************************************/ - -#include <config.h> -#include <stdio.h> -#include <assert.h> -#include <stdlib.h> -#include <ctype.h> -#include <stdarg.h> -#include "bcmath.h" -#include "private.h" - - -void bc_rt_warn (char *mesg ,...) -{ - va_list args; - char error_mesg [255]; - - va_start (args, mesg); - vsnprintf (error_mesg, sizeof(error_mesg), mesg, args); - va_end (args); - - fprintf (stderr, "bc math warning: %s\n", error_mesg); -} - - -void bc_rt_error (char *mesg ,...) -{ - va_list args; - char error_mesg [255]; - - va_start (args, mesg); - vsnprintf (error_mesg, sizeof(error_mesg), mesg, args); - va_end (args); - - fprintf (stderr, "bc math error: %s\n", error_mesg); -} diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c index ef505e86e1..62544de80e 100644 --- a/ext/bcmath/libbcmath/src/str2num.c +++ b/ext/bcmath/libbcmath/src/str2num.c @@ -105,5 +105,8 @@ bc_str2num (bc_num *num, char *str, int scale) for (;strscale > 0; strscale--) *nptr++ = CH_VAL(*ptr++); } + + if (bc_is_zero (*num)) + (*num)->n_sign = PLUS; } diff --git a/ext/bcmath/tests/bcpow_error1.phpt b/ext/bcmath/tests/bcpow_error1.phpt new file mode 100644 index 0000000000..d3189f062a --- /dev/null +++ b/ext/bcmath/tests/bcpow_error1.phpt @@ -0,0 +1,15 @@ +--TEST-- +bcpow() does not support non-integral exponents +--SKIPIF-- +<?php +if (!extension_loaded('bcmath')) die('skip bcmath extension is not available'); +?> +--FILE-- +<?php +var_dump(bcpow('1', '1.1', 2)); +?> +===DONE=== +--EXPECTF-- +Warning: bcpow(): non-zero scale in exponent in %s on line %d +string(4) "1.00" +===DONE=== diff --git a/ext/bcmath/tests/bcpow_error2.phpt b/ext/bcmath/tests/bcpow_error2.phpt new file mode 100644 index 0000000000..49fd0b88d3 --- /dev/null +++ b/ext/bcmath/tests/bcpow_error2.phpt @@ -0,0 +1,15 @@ +--TEST-- +bcpow() does not support exponents >= 2**63 +--SKIPIF-- +<?php +if (!extension_loaded('bcmath')) die('skip bcmath extension is not available'); +?> +--FILE-- +<?php +var_dump(bcpow('0', '9223372036854775808', 2)); +?> +===DONE=== +--EXPECTF-- +Warning: bcpow(): exponent too large in %s on line %d +string(4) "1.00" +===DONE=== diff --git a/ext/bcmath/tests/bcscale_variation003.phpt b/ext/bcmath/tests/bcscale_variation003.phpt new file mode 100644 index 0000000000..b1c541644c --- /dev/null +++ b/ext/bcmath/tests/bcscale_variation003.phpt @@ -0,0 +1,18 @@ +--TEST-- +bcscale() return value +--SKIPIF-- +<?php if(!extension_loaded("bcmath")) print "skip"; ?> +--INI-- +bcmath.scale=0 +--FILE-- +<?php +var_dump(bcscale(1)); +var_dump(bcscale(4)); +var_dump(bcscale()); +var_dump(bcscale()); +?> +--EXPECT-- +int(0) +int(1) +int(4) +int(4) diff --git a/ext/bcmath/tests/bug46781.phpt b/ext/bcmath/tests/bug46781.phpt new file mode 100644 index 0000000000..caffe83860 --- /dev/null +++ b/ext/bcmath/tests/bug46781.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #46781 (BC math handles minus zero incorrectly) +--SKIPIF-- +<?php +if (!extension_loaded('bcmath')) die('skip bcmath extension is not available'); +?> +--FILE-- +<?php +var_dump(bcadd('-0.0', '-0.0', 1)); +var_dump(bccomp('-0.0', '0', 1)); +?> +===DONE=== +--EXPECT-- +string(3) "0.0" +int(0) +===DONE=== diff --git a/ext/bcmath/tests/bug72093-win32.phpt b/ext/bcmath/tests/bug72093-win32.phpt deleted file mode 100644 index a9b2077823..0000000000 --- a/ext/bcmath/tests/bug72093-win32.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Bug 72093: bcpowmod accepts negative scale and corrupts _one_ definition ---SKIPIF-- -<?php -if(!extension_loaded("bcmath")) print "skip"; -if (substr(PHP_OS, 0, 3) != 'WIN') { - die('skip valid only for windows'); -} -?> ---FILE-- -<?php -var_dump(bcpowmod(1, "A", 128, -200)); -var_dump(bcpowmod(1, 1.2, 1, 1)); -?> ---EXPECTF-- -string(1) "1" -string(3) "0.0" -bc math warning: non-zero scale in exponent diff --git a/ext/bcmath/tests/bug72093.phpt b/ext/bcmath/tests/bug72093.phpt index 911af5698f..3aca87a39c 100644 --- a/ext/bcmath/tests/bug72093.phpt +++ b/ext/bcmath/tests/bug72093.phpt @@ -3,9 +3,6 @@ Bug 72093: bcpowmod accepts negative scale and corrupts _one_ definition --SKIPIF-- <?php if(!extension_loaded("bcmath")) print "skip"; -if (substr(PHP_OS, 0, 3) == 'WIN') { - die('skip Not valid for windows'); -} ?> --FILE-- <?php @@ -14,5 +11,6 @@ var_dump(bcpowmod(1, 1.2, 1, 1)); ?> --EXPECTF-- string(1) "1" -bc math warning: non-zero scale in exponent + +Warning: bcpowmod(): non-zero scale in exponent in %s on line %d string(3) "0.0" diff --git a/ext/bcmath/tests/bug75178.phpt b/ext/bcmath/tests/bug75178.phpt new file mode 100644 index 0000000000..e7661755ad --- /dev/null +++ b/ext/bcmath/tests/bug75178.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus) +--SKIPIF-- +<?php +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)); +?> +===DONE=== +--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" +===DONE=== |