From 1b2d14c5e10cc024f97a257a00fbefdb3a906501 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Mon, 21 Feb 2011 06:53:24 +0000 Subject: [PATCH] - Fixed bug #54055 (buffer overrun with high values for precision ini setting). #This fix (for g/G/k/H modes) is done at a different level than that for the #modes e/E/f/F, at a bit higher level and therefore with less coverage. I #chose this because it addresses the problem where it is -- the calling function #that passes a buffer too small to php_gcvt. --- NEWS | 2 + ext/standard/tests/strings/bug54055.phpt | 589 +++++++++++++++++++++++ main/snprintf.c | 8 +- main/snprintf.h | 13 +- main/spprintf.c | 8 +- 5 files changed, 611 insertions(+), 9 deletions(-) create mode 100644 ext/standard/tests/strings/bug54055.phpt diff --git a/NEWS b/NEWS index 0bc73ddb6b..a1a780a64e 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ authentication using stream_context/http/header/Proxy-Authorization (Dmitry) . Changed default value of ini directive serialize_precision from 100 to 17. (Gustavo) + . Fixed bug #54055 (buffer overrun with high values for precision ini + setting). (Gustavo) . Fixed bug #53959 (reflection data for fgetcsv out-of-date). (Richard) . Fixed bug #53577 (Regression introduced in 5.3.4 in open_basedir with a trailing forward slash). (lekensteyn at gmail dot com, Pierre) diff --git a/ext/standard/tests/strings/bug54055.phpt b/ext/standard/tests/strings/bug54055.phpt new file mode 100644 index 0000000000..7124c46875 --- /dev/null +++ b/ext/standard/tests/strings/bug54055.phpt @@ -0,0 +1,589 @@ +--TEST-- +Bug #54055: PHP crashes when executing strval when precision setting is very high +--FILE-- + FORMAT_CONV_MAX_PRECISION) { + precision = FORMAT_CONV_MAX_PRECISION; + } } else adjust_precision = NO; } else diff --git a/main/snprintf.h b/main/snprintf.h index 41fed76dd1..2bf7c2c180 100644 --- a/main/snprintf.h +++ b/main/snprintf.h @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Stig Sæther Bakken | + | Author: Stig Sæther Bakken | | Marcus Boerger | +----------------------------------------------------------------------+ */ @@ -158,6 +158,17 @@ extern char * ap_php_conv_10(register wide_int num, register bool_int is_unsigne extern char * ap_php_conv_p2(register u_wide_int num, register int nbits, char format, char *buf_end, register int *len); +/* The maximum precision that's allowed for float conversion. Does not include + * decimal separator, exponent, sign, terminator. Currently does not affect + * the modes e/f, only g/k/H, as those have a different limit enforced at + * another level (see NDIG in php_conv_fp()). + * Applies to the formatting functions of both spprintf.c and snprintf.c, which + * use equally sized buffers of MAX_BUF_SIZE = 512 to hold the result of the + * call to php_gcvt(). + * This should be reasonably smaller than MAX_BUF_SIZE (I think MAX_BUF_SIZE - 9 + * should be enough, but let's give some more space) */ +#define FORMAT_CONV_MAX_PRECISION 500 + #endif /* SNPRINTF_H */ /* diff --git a/main/spprintf.c b/main/spprintf.c index 635d17ca17..8c90fda378 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -285,10 +285,6 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) /* * Check if a precision was specified - * - * XXX: an unreasonable amount of precision may be specified - * resulting in overflow of num_buf. Currently we - * ignore this possibility. */ if (*fmt == '.') { adjust_precision = YES; @@ -302,6 +298,10 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) precision = 0; } else precision = 0; + + if (precision > FORMAT_CONV_MAX_PRECISION) { + precision = FORMAT_CONV_MAX_PRECISION; + } } else adjust_precision = NO; } else -- 2.50.1