[Pcre-svn] [399] code/trunk: Fix regerror() small buffer iss…

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [399] code/trunk: Fix regerror() small buffer issues.
Revision: 399
          http://www.exim.org/viewvc/pcre2?view=rev&revision=399
Author:   ph10
Date:     2015-10-30 17:17:40 +0000 (Fri, 30 Oct 2015)
Log Message:
-----------
Fix regerror() small buffer issues.


Modified Paths:
--------------
    code/trunk/ChangeLog
    code/trunk/doc/pcre2posix.3
    code/trunk/src/pcre2posix.c
    code/trunk/src/pcre2test.c
    code/trunk/testdata/testinput18
    code/trunk/testdata/testoutput18


Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/ChangeLog    2015-10-30 17:17:40 UTC (rev 399)
@@ -226,7 +226,10 @@
 make it easier to test long repetitive patterns. The tests for 63 above are 
 converted to use the new feature.


+66. In the POSIX wrapper, if regerror() was given too small a buffer, it could
+misbehave.

+
Version 10.20 30-June-2015
--------------------------


Modified: code/trunk/doc/pcre2posix.3
===================================================================
--- code/trunk/doc/pcre2posix.3    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/doc/pcre2posix.3    2015-10-30 17:17:40 UTC (rev 399)
@@ -1,4 +1,4 @@
-.TH PCRE2POSIX 3 "03 September 2015" "PCRE2 10.21"
+.TH PCRE2POSIX 3 "30 October 2015" "PCRE2 10.21"
 .SH NAME
 PCRE2 - Perl-compatible regular expressions (revised API)
 .SH "SYNOPSIS"
@@ -240,9 +240,11 @@
 The \fBregerror()\fP function maps a non-zero errorcode from either
 \fBregcomp()\fP or \fBregexec()\fP to a printable message. If \fIpreg\fP is not
 NULL, the error should have arisen from the use of that structure. A message
-terminated by a binary zero is placed in \fIerrbuf\fP. The length of the
-message, including the zero, is limited to \fIerrbuf_size\fP. The yield of the
-function is the size of buffer needed to hold the whole message.
+terminated by a binary zero is placed in \fIerrbuf\fP. If the buffer is too
+short, only the first \fIerrbuf_size\fP - 1 characters of the error message are
+used. The yield of the function is the size of buffer needed to hold the whole
+message, including the terminating zero. This value is greater than
+\fIerrbuf_size\fP if the message was truncated.
 .
 .
 .SH MEMORY USAGE
@@ -267,6 +269,6 @@
 .rs
 .sp
 .nf
-Last updated: 03 September 2015
+Last updated: 30 October 2015
 Copyright (c) 1997-2015 University of Cambridge.
 .fi


Modified: code/trunk/src/pcre2posix.c
===================================================================
--- code/trunk/src/pcre2posix.c    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/src/pcre2posix.c    2015-10-30 17:17:40 UTC (rev 399)
@@ -144,29 +144,23 @@
 PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION
 regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
 {
-const char *message, *addmessage;
-size_t length, addlength;
+int used;
+const char *message;


message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))?
"unknown error code" : pstring[errcode];
-length = strlen(message) + 1;

-addmessage = " at offset ";
-addlength = (preg != NULL && (int)preg->re_erroffset != -1)?
-  strlen(addmessage) + 6 : 0;
-
-if (errbuf_size > 0)
+if (preg != NULL && (int)preg->re_erroffset != -1)
   {
-  if (addlength > 0 && errbuf_size >= length + addlength)
-    sprintf(errbuf, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset);
-  else
-    {
-    strncpy(errbuf, message, errbuf_size - 1);
-    errbuf[errbuf_size-1] = 0;
-    }
+  used = snprintf(errbuf, errbuf_size, "%s at offset %-6d", message, 
+    (int)preg->re_erroffset);
   }
-
-return length + addlength;
+else
+  {
+  used = snprintf(errbuf, errbuf_size, "%s", message);
+  }
+  
+return used + 1;      
 }




Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/src/pcre2test.c    2015-10-30 17:17:40 UTC (rev 399)
@@ -445,6 +445,7 @@
   uint32_t  jit;
   uint32_t  stackguard_test;
   uint32_t  tables_id;
+  uint32_t  regerror_buffsize; 
    uint8_t  locale[LOCALESIZE];
 } patctl;


@@ -566,6 +567,7 @@
   { "ps",                  MOD_DAT,  MOD_OPT, PCRE2_PARTIAL_SOFT,        DO(options) },
   { "push",                MOD_PAT,  MOD_CTL, CTL_PUSH,                  PO(control) },
   { "recursion_limit",     MOD_CTM,  MOD_INT, 0,                         MO(recursion_limit) },
+  { "regerror_buffsize",   MOD_PAT,  MOD_INT, 0,                         PO(regerror_buffsize) },
   { "replace",             MOD_PND,  MOD_STR, REPLACE_MODSIZE,           PO(replacement) },
   { "stackguard",          MOD_PAT,  MOD_INT, 0,                         PO(stackguard_test) },
   { "startchar",           MOD_PND,  MOD_CTL, CTL_STARTCHAR,             PO(control) },
@@ -774,7 +776,7 @@
 Pattern lines are always copied to pbuffer8 for use in callouts, even if they
 are actually compiled from pbuffer16 or pbuffer32. */


-static int       pbuffer8_size  = 50000;        /* Initial size, bytes */
+static size_t    pbuffer8_size  = 50000;        /* Initial size, bytes */
 static uint8_t  *pbuffer8 = NULL;
 static uint8_t  *buffer = NULL;


@@ -4575,8 +4577,21 @@
   rc = regcomp(&preg, (char *)pbuffer8, cflags);
   if (rc != 0)   /* Failure */
     {
-    (void)regerror(rc, &preg, (char *)pbuffer8, pbuffer8_size);
+    size_t bsize, usize;
+     
+    bsize = (pat_patctl.regerror_buffsize != 0)?
+      pat_patctl.regerror_buffsize : pbuffer8_size; 
+    if (bsize + 8 < pbuffer8_size)
+      memcpy(pbuffer8 + bsize, "DEADBEEF", 8);
+    usize = regerror(rc, &preg, (char *)pbuffer8, bsize);
+     
     fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, pbuffer8);
+    if (usize > bsize)
+      {
+      fprintf(outfile, "** regerror() message truncated\n");
+      if (memcmp(pbuffer8 + bsize, "DEADBEEF", 8) != 0)
+        fprintf(outfile, "** regerror() buffer overflow\n");  
+      }    
     return PR_SKIP;
     }
   return PR_OK;


Modified: code/trunk/testdata/testinput18
===================================================================
--- code/trunk/testdata/testinput18    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/testdata/testinput18    2015-10-30 17:17:40 UTC (rev 399)
@@ -94,4 +94,8 @@


/abcd/substitute_extended

+/\[A]{1000000}**/expand,regerror_buffsize=31
+
+/\[A]{1000000}**/expand,regerror_buffsize=32
+
# End of testdata/testinput18

Modified: code/trunk/testdata/testoutput18
===================================================================
--- code/trunk/testdata/testoutput18    2015-10-30 16:08:51 UTC (rev 398)
+++ code/trunk/testdata/testoutput18    2015-10-30 17:17:40 UTC (rev 399)
@@ -143,4 +143,11 @@
 /abcd/substitute_extended
 ** Ignored with POSIX interface: substitute_extended


+/\[A]{1000000}**/expand,regerror_buffsize=31
+Failed: POSIX code 4: ? * + invalid at offset 100000
+** regerror() message truncated
+
+/\[A]{1000000}**/expand,regerror_buffsize=32
+Failed: POSIX code 4: ? * + invalid at offset 1000001
+
# End of testdata/testinput18