iliaa Thu Jan 9 11:54:15 2003 EDT
Added files: (Branch: PHP_4_3)
/php4/ext/standard/tests/math bug21523.phpt
Modified files:
/php4/ext/standard math.c
Log:
MFH
Index: php4/ext/standard/math.c
diff -u php4/ext/standard/math.c:1.97.2.2 php4/ext/standard/math.c:1.97.2.3
--- php4/ext/standard/math.c:1.97.2.2 Tue Dec 31 11:35:31 2002
+++ php4/ext/standard/math.c Thu Jan 9 11:54:15 2003
@@ -19,7 +19,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: math.c,v 1.97.2.2 2002/12/31 16:35:31 sebastian Exp $ */
+/* $Id: math.c,v 1.97.2.3 2003/01/09 16:54:15 iliaa Exp $ */
#include "php.h"
#include "php_math.h"
@@ -980,57 +980,91 @@
PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char
thousand_sep)
{
- char *tmpbuf, *resbuf;
+ char *tmpbuf = NULL, *resbuf;
char *s, *t; /* source, target */
+ char *dp;
+ int integral;
int tmplen, reslen=0;
int count=0;
int is_negative=0;
- if (d<0) {
- is_negative=1;
+ if (d < 0) {
+ is_negative = 1;
d = -d;
}
dec = MAX(0, dec);
- tmpbuf = (char *) emalloc(1+DBL_MAX_10_EXP+1+dec+1);
-
- tmplen=sprintf(tmpbuf, "%.*f", dec, d);
- if (!isdigit((int)tmpbuf[0])) {
+ tmplen = spprintf(&tmpbuf, 0, "%.*f", dec, d);
+
+ if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
return tmpbuf;
}
- if (dec) {
- reslen = dec+1 + (tmplen-dec-1) + ((thousand_sep) ? (tmplen-1-dec-1)/3
: 0);
+ /* calculate the length of the return buffer */
+ dp = strchr(tmpbuf, '.');
+ if (dp) {
+ integral = dp - tmpbuf;
} else {
- reslen = tmplen+((thousand_sep) ? (tmplen-1)/3 : 0);
+ /* no decimal point was found */
+ integral = tmplen;
+ }
+
+ /* allow for thousand separators */
+ if (thousand_sep) {
+ integral += integral / 3;
}
+
+ reslen = integral + 1 + dec;
+
+ /* add a byte for minus sign */
if (is_negative) {
reslen++;
}
- resbuf = (char *) emalloc(reslen+1);
-
+ resbuf = (char *) emalloc(reslen+1); /* +1 for NUL terminator */
+
s = tmpbuf+tmplen-1;
t = resbuf+reslen;
- *t-- = 0;
-
+ *t-- = '\0';
+
+ /* copy the decimal places.
+ * Take care, as the sprintf implementation may return less places than
+ * we requested due to internal buffer limitations */
if (dec) {
- while (isdigit((int)*s)) {
- *t-- = *s--;
+ int declen = dp ? strlen(dp+1) : 0;
+ int topad = declen > 0 ? dec - declen : 0;
+
+ /* pad with '0's */
+ while (topad--) {
+ *t-- = '0';
}
- *t-- = dec_point; /* copy that dot */
+
+ /* now copy the chars after the point */
+ memcpy(t - declen + 1, dp + 1, declen);
+
+ t -= declen;
+ s -= declen;
+
+ /* add decimal point */
+ *t-- = dec_point;
s--;
}
- while(s>=tmpbuf) {
+ /* copy the numbers before the decimal place, adding thousand
+ * separator every three digits */
+ while(s >= tmpbuf) {
*t-- = *s--;
if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
*t-- = thousand_sep;
}
}
+
+ /* and a minus sign, if needed */
if (is_negative) {
*t-- = '-';
}
+
efree(tmpbuf);
+
return resbuf;
}
Index: php4/ext/standard/tests/math/bug21523.phpt
+++ php4/ext/standard/tests/math/bug21523.phpt
--TEST--
Bug #21523 number_format tries to allocate negative amount of memory
--FILE--
<?php // $Id: bug21523.phpt,v 1.1 2003/01/09 15:44:49 wez Exp $ vim600:syn=php
var_dump(number_format(-2000, 2768));
echo "OK";
?>
--EXPECT--
string(2775)
"-2,000.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
OK
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php