[Pcre-svn] [252] code/trunk: Fix replication bug in pcre2tes…

Inizio della pagina
Delete this message
Autore: Subversion repository
Data:  
To: pcre-svn
Oggetto: [Pcre-svn] [252] code/trunk: Fix replication bug in pcre2test.
Revision: 252
          http://www.exim.org/viewvc/pcre2?view=rev&revision=252
Author:   ph10
Date:     2015-04-21 09:34:10 +0100 (Tue, 21 Apr 2015)


Log Message:
-----------
Fix replication bug in pcre2test.

Modified Paths:
--------------
    code/trunk/ChangeLog
    code/trunk/src/pcre2test.c
    code/trunk/testdata/testinput2
    code/trunk/testdata/testoutput2


Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog    2015-04-21 07:02:08 UTC (rev 251)
+++ code/trunk/ChangeLog    2015-04-21 08:34:10 UTC (rev 252)
@@ -87,7 +87,12 @@


21. Implemented PCRE2_NEVER_BACKSLASH_C.

+22. The feature for string replication in pcre2test could read from freed
+memory if the replication required a buffer to be extended, and it was not
+working properly in 16-bit and 32-bit modes. This issue was discovered by a
+fuzzer: see http://lcamtuf.coredump.cx/afl/.

+
Version 10.10 06-March-2015
---------------------------


Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c    2015-04-21 07:02:08 UTC (rev 251)
+++ code/trunk/src/pcre2test.c    2015-04-21 08:34:10 UTC (rev 252)
@@ -1181,11 +1181,11 @@


 #define SETCASTPTR(x,y) \
   if (test_mode == PCRE8_MODE) \
-    G(x,8) = (uint8_t *)y; \
+    G(x,8) = (uint8_t *)(y); \
   else if (test_mode == PCRE16_MODE) \
-    G(x,16) = (uint16_t *)y; \
+    G(x,16) = (uint16_t *)(y); \
   else \
-    G(x,32) = (uint32_t *)y
+    G(x,32) = (uint32_t *)(y)


#define STRLEN(p) ((test_mode == PCRE8_MODE)? ((int)strlen((char *)p)) : \
(test_mode == PCRE16_MODE)? ((int)strlen16((PCRE2_SPTR16)p)) : \
@@ -1563,9 +1563,9 @@

 #define SETCASTPTR(x,y) \
   if (test_mode == G(G(PCRE,BITONE),_MODE)) \
-    G(x,BITONE) = (G(G(uint,BITONE),_t) *)y; \
+    G(x,BITONE) = (G(G(uint,BITONE),_t) *)(y); \
   else \
-    G(x,BITTWO) = (G(G(uint,BITTWO),_t) *)y
+    G(x,BITTWO) = (G(G(uint,BITTWO),_t) *)(y)


#define STRLEN(p) ((test_mode == G(G(PCRE,BITONE),_MODE))? \
G(strlen,BITONE)((G(PCRE2_SPTR,BITONE))p) : \
@@ -1680,7 +1680,7 @@
#define SETFLD(x,y,z) G(x,8)->y = z
#define SETFLDVEC(x,y,v,z) G(x,8)->y[v] = z
#define SETOP(x,y,z) G(x,8) z y
-#define SETCASTPTR(x,y) G(x,8) = (uint8_t *)y
+#define SETCASTPTR(x,y) G(x,8) = (uint8_t *)(y)
#define STRLEN(p) (int)strlen((char *)p)
#define SUB1(a,b) G(a,8)(G(b,8))
#define SUB2(a,b,c) G(a,8)(G(b,8),G(c,8))
@@ -1771,7 +1771,7 @@
#define SETFLD(x,y,z) G(x,16)->y = z
#define SETFLDVEC(x,y,v,z) G(x,16)->y[v] = z
#define SETOP(x,y,z) G(x,16) z y
-#define SETCASTPTR(x,y) G(x,16) = (uint16_t *)y
+#define SETCASTPTR(x,y) G(x,16) = (uint16_t *)(y)
#define STRLEN(p) (int)strlen16((PCRE2_SPTR16)p)
#define SUB1(a,b) G(a,16)(G(b,16))
#define SUB2(a,b,c) G(a,16)(G(b,16),G(c,16))
@@ -1862,7 +1862,7 @@
#define SETFLD(x,y,z) G(x,32)->y = z
#define SETFLDVEC(x,y,v,z) G(x,32)->y[v] = z
#define SETOP(x,y,z) G(x,32) z y
-#define SETCASTPTR(x,y) G(x,32) = (uint32_t *)y
+#define SETCASTPTR(x,y) G(x,32) = (uint32_t *)(y)
#define STRLEN(p) (int)strlen32((PCRE2_SPTR32)p)
#define SUB1(a,b) G(a,32)(G(b,32))
#define SUB2(a,b,c) G(a,32)(G(b,32),G(c,32))
@@ -5079,12 +5079,13 @@
#endif

/* Allocate a buffer to hold the data line; len+1 is an upper bound on
-the number of code units that will be needed. */
+the number of code units that will be needed (though the buffer may have to be
+extended if replication is involved). */

 needlen = (size_t)(len * code_unit_size);
-while (dbuffer == NULL || needlen >= dbuffer_size)
+if (dbuffer == NULL || needlen >= dbuffer_size)
   {
-  dbuffer_size *= 2;
+  while (needlen >= dbuffer_size) dbuffer_size *= 2;
   dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size);
   if (dbuffer == NULL)
     {
@@ -5095,7 +5096,7 @@
 SETCASTPTR(q, dbuffer);  /* Sets q8, q16, or q32, as appropriate. */


/* Scan the data line, interpreting data escapes, and put the result into a
-buffer the appropriate width buffer. In UTF mode, input can be UTF-8. */
+buffer of the appropriate width. In UTF mode, input can be UTF-8. */

while ((c = *p++) != 0)
{
@@ -5106,7 +5107,8 @@

   if (c == ']' && start_rep != NULL)
     {
-    size_t qoffset = CAST8VAR(q) - (uint8_t *)dbuffer;
+    size_t qoffset = CAST8VAR(q) - dbuffer;
+    size_t rep_offset = start_rep - dbuffer;


     if (*p++ != '{')
       {
@@ -5126,10 +5128,11 @@
       }


     replen = CAST8VAR(q) - start_rep;
-    needlen += replen * (i - 1);
-    while (needlen >= dbuffer_size)
+    needlen += replen * i;
+    
+    if (needlen >= dbuffer_size)
       {
-      dbuffer_size *= 2;
+      while (needlen >= dbuffer_size) dbuffer_size *= 2;
       dbuffer = (uint8_t *)realloc(dbuffer, dbuffer_size);
       if (dbuffer == NULL)
         {
@@ -5137,8 +5140,9 @@
         exit(1);
         }
       SETCASTPTR(q, dbuffer + qoffset);
+      start_rep = dbuffer + rep_offset;
       }
-
+      
     while (i-- > 0)
       {
       memcpy(CAST8VAR(q), start_rep, replen);


Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2    2015-04-21 07:02:08 UTC (rev 251)
+++ code/trunk/testdata/testinput2    2015-04-21 08:34:10 UTC (rev 252)
@@ -4267,4 +4267,10 @@


/ab\Cde/never_backslash_c

+/abc/
+    \[9x!xxx(]{9999}
+    
+/(abc)*/
+    \[abc]{5} 
+
 # End of testinput2 


Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2    2015-04-21 07:02:08 UTC (rev 251)
+++ code/trunk/testdata/testoutput2    2015-04-21 08:34:10 UTC (rev 252)
@@ -14296,4 +14296,13 @@
 /ab\Cde/never_backslash_c
 Failed: error 183 at offset 3: using \C is disabled by the application


+/abc/
+    \[9x!xxx(]{9999}
+No match
+    
+/(abc)*/
+    \[abc]{5} 
+ 0: abcabcabcabcabc
+ 1: abc
+
 # End of testinput2