From b9969d3137e52a159eaf9f9f38aba34c910b204c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 1 Jan 2023 16:32:56 +0100 Subject: [PATCH] Fix GH-9209: precision 0 -INF As suggested by cmb69, this is fixed by changing zend_gcvt() and verifying whether the callers have enough buffer space. --- Zend/tests/gh9209.phpt | 18 ++++++++++++++++++ Zend/zend_strtod.c | 2 +- ext/soap/php_encoding.c | 3 ++- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh9209.phpt diff --git a/Zend/tests/gh9209.phpt b/Zend/tests/gh9209.phpt new file mode 100644 index 000000000000..a85df4ae23c8 --- /dev/null +++ b/Zend/tests/gh9209.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-9209 (precision 0 -INF) +--FILE-- + +--EXPECT-- +string(3) "INF" +string(4) "-INF" +string(3) "NAN" +string(3) "NAN" +string(4) "-123" diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 3e7f90378ef5..e48b7a00e59c 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -4523,7 +4523,7 @@ ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent * Infinity or NaN, convert to inf or nan with sign. * We assume the buffer is at least ndigit long. */ - snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN"); + snprintf(buf, (sign && *digits == 'I') + 4, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN"); zend_freedtoa(digits); return (buf); } diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 3a4626aa5bee..0fabb85cf69d 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1078,7 +1078,8 @@ static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNo ZVAL_DOUBLE(&tmp, zval_get_double(data)); - str = (char *) safe_emalloc(EG(precision) >= 0 ? EG(precision) : 17, 1, MAX_LENGTH_OF_DOUBLE + 1); + /* We need at least 5 bytes for the -INF exceptional case. */ + str = (char *) safe_emalloc(EG(precision) >= 0 ? MAX(EG(precision), 5) : 17, 1, MAX_LENGTH_OF_DOUBLE + 1); zend_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str); xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str)); efree(str);