diff options
author | Stanislav Malyshev <stas@php.net> | 2007-06-06 18:38:47 +0000 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2007-06-06 18:38:47 +0000 |
commit | 25df29e22332eced1fe666c00800c4f37918d105 (patch) | |
tree | 2803ae805fd2705c50e00e1eac31ec70d9b1fc52 | |
parent | 58feae40d81a71c8e7d986cc3e5e41b814b59578 (diff) | |
download | php-git-25df29e22332eced1fe666c00800c4f37918d105.tar.gz |
Fix chunk_split fix - avoid using floats
Fix money_format - don't give strfmon more arguments then supplied
Fix str[c]spn integer overflow
-rw-r--r-- | ext/standard/string.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c index b7b36afba8..66773a9520 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -234,10 +234,14 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) } } - if (((unsigned) start + (unsigned) len) > len1) { + if (len > len1 - start) { len = len1 - start; } + if(len == 0) { + RETURN_LONG(0); + } + s = s22; e = s22 + len2; while (s < e) { @@ -1511,20 +1515,25 @@ static PHP_ATTRIBUTE_MALLOC char *php_chunk_split(char *src, int srclen, char *e char *p, *q; int chunks; /* complete chunks! */ int restlen; - float out_len; + int out_len; chunks = srclen / chunklen; restlen = srclen - chunks * chunklen; /* srclen % chunklen */ + if(chunks > INT_MAX - 1) { + return NULL; + } out_len = chunks + 1; + if(endlen != 0 && out_len > INT_MAX/endlen) { + return NULL; + } out_len *= endlen; - out_len += srclen + 1; - - if (out_len > INT_MAX || out_len <= 0) { + if(out_len > INT_MAX - srclen - 1) { return NULL; } + out_len += srclen + 1; - dest = safe_emalloc((int)out_len, sizeof(char), 0); + dest = safe_emalloc(out_len, sizeof(char), 0); for (p = src, q = dest; p < (src + srclen - chunklen + 1); ) { memcpy(q, p, chunklen); @@ -4097,14 +4106,29 @@ PHP_FUNCTION(str_word_count) PHP_FUNCTION(money_format) { int format_len = 0, str_len; - char *format, *str; + char *format, *str, *p, *e; double value; + zend_bool check = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sd", &format, &format_len, &value) == FAILURE) { return; } + p = format; + e = p + format_len; + while ((p = memchr(p, '%', (e - p)))) { + if (*(p + 1) == '%') { + p += 2; + } else if (!check) { + check = 1; + p++; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only a single %%i or %%n token can be used"); + RETURN_FALSE; + } + } + str_len = format_len + 1024; str = emalloc(str_len); if ((str_len = strfmon(str, str_len, format, value)) < 0) { |