summaryrefslogtreecommitdiff
path: root/ext/bcmath
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bcmath')
-rw-r--r--ext/bcmath/bcmath.c17
-rw-r--r--ext/bcmath/config.m42
-rw-r--r--ext/bcmath/config.w322
-rw-r--r--ext/bcmath/libbcmath/src/bcmath.h2
-rw-r--r--ext/bcmath/libbcmath/src/raise.c4
-rw-r--r--ext/bcmath/libbcmath/src/raisemod.c48
-rw-r--r--ext/bcmath/libbcmath/src/rt.c65
-rw-r--r--ext/bcmath/libbcmath/src/str2num.c3
-rw-r--r--ext/bcmath/tests/bcpow_error1.phpt15
-rw-r--r--ext/bcmath/tests/bcpow_error2.phpt15
-rw-r--r--ext/bcmath/tests/bcscale_variation003.phpt18
-rw-r--r--ext/bcmath/tests/bug46781.phpt16
-rw-r--r--ext/bcmath/tests/bug72093-win32.phpt18
-rw-r--r--ext/bcmath/tests/bug72093.phpt6
-rw-r--r--ext/bcmath/tests/bug75178.phpt19
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===