[Pcre-svn] [485] code/trunk: Detect and warn when pcre2test …

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [485] code/trunk: Detect and warn when pcre2test is linked with an alien POSIX library.
Revision: 485
          http://www.exim.org/viewvc/pcre2?view=rev&revision=485
Author:   ph10
Date:     2016-02-03 15:22:01 +0000 (Wed, 03 Feb 2016)
Log Message:
-----------
Detect and warn when pcre2test is linked with an alien POSIX library.


Modified Paths:
--------------
    code/trunk/ChangeLog
    code/trunk/src/pcre2posix.c
    code/trunk/src/pcre2posix.h
    code/trunk/src/pcre2test.c


Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog    2016-02-02 17:22:55 UTC (rev 484)
+++ code/trunk/ChangeLog    2016-02-03 15:22:01 UTC (rev 485)
@@ -42,7 +42,19 @@
 misleading incorrect error message. For example, /(?J)(?'a'))(?'a')/ gave a
 message about invalid duplicate group names.


+10. It has happened that pcre2test was accidentally linked with another POSIX
+regex library instead of libpcre2-posix. In this situation, a call to regcomp()
+(in the other library) may succeed, returning zero, but of course putting its
+own data into the regex_t block. In one example the re_pcre2_code field was
+left as NULL, which made pcre2test think it had not got a compiled POSIX regex,
+so it treated the next line as another pattern line, resulting in a confusing
+error message. A check has been added to pcre2test to see if the data returned
+from a successful call of regcomp() are valid for PCRE2's regcomp(). If they
+are not, an error message is output and the pcre2test run is abandoned. The
+message points out the possibility of a mis-linking. Hopefully this will avoid
+some head-scratching the next time this happens.

+
Version 10.21 12-January-2016
-----------------------------


Modified: code/trunk/src/pcre2posix.c
===================================================================
--- code/trunk/src/pcre2posix.c    2016-02-02 17:22:55 UTC (rev 484)
+++ code/trunk/src/pcre2posix.c    2016-02-03 15:22:01 UTC (rev 485)
@@ -209,7 +209,7 @@
 if ((cflags & REG_UCP) != 0)      options |= PCRE2_UCP;
 if ((cflags & REG_UNGREEDY) != 0) options |= PCRE2_UNGREEDY;


-preg->cflags = cflags;
+preg->re_cflags = cflags;
 preg->re_pcre2_code = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED,
    options, &errorcode, &erroffset, NULL);
 preg->re_erroffset = erroffset;
@@ -275,7 +275,7 @@
 put captured strings, ensure that nmatch is zero. This will stop any attempt to
 write to pmatch. */


-if ((preg->cflags & REG_NOSUB) != 0 || pmatch == NULL) nmatch = 0;
+if ((preg->re_cflags & REG_NOSUB) != 0 || pmatch == NULL) nmatch = 0;

/* REG_STARTEND is a BSD extension, to allow for non-NUL-terminated strings.
The man page from OS X says "REG_STARTEND affects only the location of the

Modified: code/trunk/src/pcre2posix.h
===================================================================
--- code/trunk/src/pcre2posix.h    2016-02-02 17:22:55 UTC (rev 484)
+++ code/trunk/src/pcre2posix.h    2016-02-03 15:22:01 UTC (rev 485)
@@ -98,7 +98,7 @@
   void *re_match_data;
   size_t re_nsub;
   size_t re_erroffset;
-  int cflags;
+  int re_cflags;
 } regex_t;


/* The structure in which a captured offset is returned. */

Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c    2016-02-02 17:22:55 UTC (rev 484)
+++ code/trunk/src/pcre2test.c    2016-02-03 15:22:01 UTC (rev 485)
@@ -2982,7 +2982,7 @@
     the buffer or reached the end of the file. We can detect the former by
     checking that the string fills the buffer, and the latter by feof(). If
     neither of these is true, it means we read a binary zero which has caused
-    strlen() to give a short length. This is a hard error because pcre2test 
+    strlen() to give a short length. This is a hard error because pcre2test
     expects to work with C strings. */


     if (!INTERACTIVE(f) && dlen < rlen - 1 && !feof(f))
@@ -4701,8 +4701,7 @@


if (msg[0] == 0) fprintf(outfile, "\n");

- /* Translate PCRE2 options to POSIX options and then compile. On success, set
- up a match_data block to be used for all matches. */
+ /* Translate PCRE2 options to POSIX options and then compile. */

if (utf) cflags |= REG_UTF;
if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0) cflags |= REG_NOSUB;
@@ -4713,7 +4712,10 @@
if ((pat_patctl.options & PCRE2_UNGREEDY) != 0) cflags |= REG_UNGREEDY;

   rc = regcomp(&preg, (char *)pbuffer8, cflags);
-  if (rc != 0)   /* Failure */
+
+  /* Compiling failed */
+
+  if (rc != 0)
     {
     size_t bsize, usize;


@@ -4735,6 +4737,29 @@
       }
     return PR_SKIP;
     }
+
+  /* Compiling succeeded. Check that the values in the preg block are sensible.
+  It can happen that pcre2test is accidentally linked with a different POSIX
+  library which succeeds, but of course puts different things into preg. In
+  this situation, calling regfree() may cause a segfault (or invalid free() in
+  valgrind), so ensure that preg.re_pcre2_code is NULL, which suppresses the
+  calling of regfree() on exit. */
+
+  if (preg.re_pcre2_code == NULL ||
+      ((pcre2_real_code_8 *)preg.re_pcre2_code)->magic_number != MAGIC_NUMBER ||
+      ((pcre2_real_code_8 *)preg.re_pcre2_code)->top_bracket != preg.re_nsub ||
+      preg.re_match_data == NULL ||
+      preg.re_cflags != cflags)
+    {
+    fprintf(outfile,
+      "** The regcomp() function returned zero (success), but the values set\n"
+      "** in the preg block are not valid for PCRE2. Check that pcre2test is\n"
+      "** linked with PCRE2's pcre2posix module (-lpcre2-posix) and not with\n"
+      "** some other POSIX regex library.\n**\n");
+    preg.re_pcre2_code = NULL;
+    return PR_ABEND;
+    }
+
   return PR_OK;
 #endif  /* SUPPORT_PCRE2_8 */
   }
@@ -7450,7 +7475,7 @@
 #ifdef SUPPORT_PCRE2_8
 #undef BITS
 #define BITS 8
-regfree(&preg);
+if (preg.re_pcre2_code != NULL) regfree(&preg);
 FREECONTEXTS;
 #endif