I didn't carefully review this patch, but doesn't this code suffer from potential math overflow?
i.e. with strlen($input_str) > INT_MAX/2  (or UINT_MAX/2)

Nuno

----- Original Message ----- From: "Gustavo André dos Santos Lopes" <cataphr...@php.net>
To: <php-cvs@lists.php.net>
Sent: Sunday, February 05, 2012 9:59 AM
Subject: [PHP-CVS] svn: /php/php-src/branches/PHP_5_4/ NEWS ext/standard/html.c ext/standard/tests/strings/bug60965.phpt


cataphract                               Sun, 05 Feb 2012 09:59:33 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=323074

Log:
- Merge r323056 (see bug #60965).

Bug: https://bugs.php.net/60965 (Critical) Buffer overflow on htmlspecialchars/entities with $double=false

Changed paths:
   U   php/php-src/branches/PHP_5_4/NEWS
   U   php/php-src/branches/PHP_5_4/ext/standard/html.c
A + php/php-src/branches/PHP_5_4/ext/standard/tests/strings/bug60965.phpt (from php/php-src/trunk/ext/standard/tests/strings/bug60965.phpt:r323056)

Modified: php/php-src/branches/PHP_5_4/NEWS
===================================================================
--- php/php-src/branches/PHP_5_4/NEWS 2012-02-05 09:58:50 UTC (rev 323073)
+++ php/php-src/branches/PHP_5_4/NEWS 2012-02-05 09:59:33 UTC (rev 323074)
@@ -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.

Modified: php/php-src/branches/PHP_5_4/ext/standard/html.c
===================================================================
--- php/php-src/branches/PHP_5_4/ext/standard/html.c 2012-02-05 09:58:50 UTC (rev 323073) +++ php/php-src/branches/PHP_5_4/ext/standard/html.c 2012-02-05 09:59:33 UTC (rev 323074)
@@ -1215,7 +1215,6 @@
 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 @@
 }
 }

+ /* 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 @@
 /* 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 @@
 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 @@
 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 @@
 }
 }
 /* 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;

Copied: php/php-src/branches/PHP_5_4/ext/standard/tests/strings/bug60965.phpt (from rev 323056, php/php-src/trunk/ext/standard/tests/strings/bug60965.phpt)
===================================================================
--- php/php-src/branches/PHP_5_4/ext/standard/tests/strings/bug60965.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/ext/standard/tests/strings/bug60965.phpt 2012-02-05 09:59:33 UTC (rev 323074)
@@ -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.


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to