Vulnerability: Perl before 5.26.3 has a buffer over-read via a crafted regular expression that triggers disclosure of sensitive information from process memory.
Vulnerability ID: CVE-2018-18313
CWE: CWE-125
Severity score: 4.9
Project: https://github.com/Perl/perl5
Published: 2018-12-07
File: regcomp.c
Commit message: regcomp.c: Convert some strchr to memchr

This allows things to work properly in the face of embedded NULs.
See the branch merge message for more information.
Commit author: Karl Williamson

Vulnerable version (before fix):
 S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state,      RExC_parse++;	/* Skip past the '{' */      endbrace = strchr(RExC_parse, '}');     if (! endbrace) { /* no trailing brace */         vFAIL2("Missing right brace on \\%c{}", 'N');     } S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)             else {                 STRLEN length;                 char name = *RExC_parse;                 char * endbrace;                 RExC_parse += 2;                 endbrace = strchr(RExC_parse, '}');                  if (! endbrace) {                     vFAIL2("Missing right brace on \\%c{}", name); S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth, 		    vFAIL2("Empty \\%c", (U8)value); 		if (*RExC_parse == '{') { 		    const U8 c = (U8)value; 		    e = strchr(RExC_parse, '}');                     if (!e) {                         RExC_parse++;                         vFAIL2("Missing right brace on \\%c{}", c);

Fixed version (after fix):
 S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state,      RExC_parse++;	/* Skip past the '{' */      endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);     if (! endbrace) { /* no trailing brace */         vFAIL2("Missing right brace on \\%c{}", 'N');     } S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)             else {                 STRLEN length;                 char name = *RExC_parse;                 char * endbrace = NULL;                 RExC_parse += 2;                 if (RExC_parse < RExC_end) {                     endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);                 }                  if (! endbrace) {                     vFAIL2("Missing right brace on \\%c{}", name); S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth, 		    vFAIL2("Empty \\%c", (U8)value); 		if (*RExC_parse == '{') { 		    const U8 c = (U8)value; 		    e = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);                     if (!e) {                         RExC_parse++;                         vFAIL2("Missing right brace on \\%c{}", c);

Patch:
patch: @@ -12056,7 +12056,7 @@ S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state,
 
     RExC_parse++;	/* Skip past the '{' */
 
-    endbrace = strchr(RExC_parse, '}');
+    endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);
     if (! endbrace) { /* no trailing brace */
         vFAIL2("Missing right brace on \\%c{}", 'N');
     }
@@ -12773,9 +12773,11 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
             else {
                 STRLEN length;
                 char name = *RExC_parse;
-                char * endbrace;
+                char * endbrace = NULL;
                 RExC_parse += 2;
-                endbrace = strchr(RExC_parse, '}');
+                if (RExC_parse < RExC_end) {
+                    endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);
+                }
 
                 if (! endbrace) {
                     vFAIL2("Missing right brace on \\%c{}", name);
@@ -16312,7 +16314,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
 		    vFAIL2("Empty \\%c", (U8)value);
 		if (*RExC_parse == '{') {
 		    const U8 c = (U8)value;
-		    e = strchr(RExC_parse, '}');
+		    e = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse);
                     if (!e) {
                         RExC_parse++;
                         vFAIL2("Missing right brace on \\%c{}", c);
path: regcomp.c