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