]> granicus.if.org Git - php/commitdiff
- Merge r323056 (see bug #60965).
authorGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 5 Feb 2012 09:59:33 +0000 (09:59 +0000)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 5 Feb 2012 09:59:33 +0000 (09:59 +0000)
NEWS
ext/standard/html.c
ext/standard/tests/strings/bug60965.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 1bfd345ab8bec59584fe4e2f8f70ef9a6b34bd69..6d64e4dbafe0f796ec69cd8c89fc119fa7c23003 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,13 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? Feb 2012, PHP 5.4.0 RC 8
+- Core:
+  . Fixed bug #60965 (Buffer overflow on htmlspecialchars/entities with
+    $double=false). (Gustavo)
 
 02 Feb 2012, PHP 5.4.0 RC 7
 - Core:
-  . Fix bug #60895 (Possible invalid handler usage in windows random
+  . Fixed bug #60895 (Possible invalid handler usage in windows random
     functions). (Pierre)
   . Fixed bug #51860 (Include fails with toplevel symlink to /). (Dmitry)
   . Fixed (disabled) inline-caching for ZEND_OVERLOADED_FUNCTION methods.
index c4bc50408017a7df9fe7e52a0c9d47df94c3990b..1d031195ba0ae9228a254ae79df803a706be97e3 100644 (file)
@@ -1215,7 +1215,6 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
        size_t cursor, maxlen, len;
        char *replaced;
        enum entity_charset charset = determine_charset(hint_charset TSRMLS_CC);
-       int matches_map;
        int doctype = flags & ENT_HTML_DOC_TYPE_MASK;
        entity_table_opt entity_table;
        const enc_to_uni *to_uni_table = NULL;
@@ -1253,12 +1252,14 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
                }
        }
 
+       /* initial estimate */
        if (oldlen < 64) {
                maxlen = 128;   
        } else {
                maxlen = 2 * oldlen;
        }
-       replaced = emalloc(maxlen);
+
+       replaced = emalloc(maxlen + 1);
        len = 0;
        cursor = 0;
        while (cursor < oldlen) {
@@ -1271,7 +1272,7 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
                /* guarantee we have at least 40 bytes to write.
                 * In HTML5, entities may take up to 33 bytes */
                if (len + 40 > maxlen) {
-                       replaced = erealloc(replaced, maxlen += 128);
+                       replaced = erealloc(replaced, (maxlen += 128) + 1);
                }
 
                if (status == FAILURE) {
@@ -1291,7 +1292,6 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
                        mbsequence = &old[cursor_before];
                        mbseqlen = cursor - cursor_before;
                }
-               matches_map = 0;
 
                if (this_char != '&') { /* no entity on this position */
                        const unsigned char *rep        = NULL;
@@ -1302,12 +1302,15 @@ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size
                                goto pass_char_through;
 
                        if (all) { /* false that CHARSET_PARTIAL_SUPPORT(charset) */
-                               /* look for entity for this char */
                                if (to_uni_table != NULL) {
+                                       /* !CHARSET_UNICODE_COMPAT therefore not UTF-8; since UTF-8
+                                        * is the only multibyte encoding with !CHARSET_PARTIAL_SUPPORT,
+                                        * we're using a single byte encoding */
                                        map_to_unicode(this_char, to_uni_table, &this_char);
                                        if (this_char == 0xFFFF) /* no mapping; pass through */
                                                goto pass_char_through;
                                }
+                               /* the cursor may advance */
                                find_entity_for_char(this_char, charset, entity_table.ms_table, &rep,
                                        &rep_len, old, oldlen, &cursor);
                        } else {
@@ -1397,6 +1400,10 @@ encode_amp:
                                        }
                                }
                                /* checks passed; copy entity to result */
+                               /* entity size is unbounded, we may need more memory */
+                               if (maxlen < len + ent_len + 2 /* & and ; */) {
+                                       replaced = erealloc(replaced, (maxlen += ent_len + 128) + 1);
+                               }
                                replaced[len++] = '&';
                                memcpy(&replaced[len], &old[cursor], ent_len);
                                len += ent_len;
diff --git a/ext/standard/tests/strings/bug60965.phpt b/ext/standard/tests/strings/bug60965.phpt
new file mode 100644 (file)
index 0000000..57a3b1c
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Bug #60965: Buffer overflow on htmlspecialchars/entities with $double=false
+--FILE--
+<?php
+echo htmlspecialchars('"""""""""""""""""""""""""""""""""""""""""""""&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005;',
+ENT_QUOTES, 'UTF-8', false), "\n";
+echo "Done.\n";
+--EXPECT--
+&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005;
+Done.