50a3de5
From cfb736762c1becf344ce6beaa701ff2e1abd5f9c Mon Sep 17 00:00:00 2001
50a3de5
From: Yves Orton <demerphq@gmail.com>
50a3de5
Date: Tue, 13 Sep 2016 23:14:49 +0200
50a3de5
Subject: [PATCH 4/5] fix #129267: rework gv_fetchmethod_pvn_flags separator
50a3de5
 parsing
50a3de5
MIME-Version: 1.0
50a3de5
Content-Type: text/plain; charset=UTF-8
50a3de5
Content-Transfer-Encoding: 8bit
50a3de5
50a3de5
With previous code we could overrun the end of the name when
50a3de5
the last char in the string was a colon. This reworks the code
50a3de5
so it is more clear what is going on, and so it more similar
50a3de5
to other code that also parses out package separaters in gv.c.
50a3de5
50a3de5
This is a rework of the reverted patches:
50a3de5
243ca72 rename "nend" name_cursor in Perl_gv_fetchmethod_pvn_flags
50a3de5
b053c93 fix: [perl #129267] Possible string overrun with invalid len in gv.c
50a3de5
50a3de5
Signed-off-by: Petr Písař <ppisar@redhat.com>
50a3de5
---
50a3de5
 gv.c | 36 ++++++++++++++++++++++++++----------
50a3de5
 1 file changed, 26 insertions(+), 10 deletions(-)
50a3de5
50a3de5
diff --git a/gv.c b/gv.c
50a3de5
index 07709a0..3237c53 100644
50a3de5
--- a/gv.c
50a3de5
+++ b/gv.c
50a3de5
@@ -1010,7 +1010,6 @@ Perl_gv_fetchmethod_pvn_flags(pTHX_ HV *stash, const char *name, const STRLEN le
50a3de5
 {
50a3de5
     const char * const origname = name;
50a3de5
     const char * const name_end = name + len;
50a3de5
-    const char *nend;
50a3de5
     const char *last_separator = NULL;
50a3de5
     GV* gv;
50a3de5
     HV* ostash = stash;
50a3de5
@@ -1029,16 +1028,33 @@ Perl_gv_fetchmethod_pvn_flags(pTHX_ HV *stash, const char *name, const STRLEN le
50a3de5
 	   the error reporting code.  */
50a3de5
     }
50a3de5
 
50a3de5
-    for (nend = name; *nend || nend != name_end; nend++) {
50a3de5
-	if (*nend == '\'') {
50a3de5
-	    last_separator = nend;
50a3de5
-	    name = nend + 1;
50a3de5
-	}
50a3de5
-	else if (*nend == ':' && *(nend + 1) == ':') {
50a3de5
-	    last_separator = nend++;
50a3de5
-	    name = nend + 1;
50a3de5
-	}
50a3de5
+    {
50a3de5
+        /* check if the method name is fully qualified or
50a3de5
+         * not, and separate the package name from the actual
50a3de5
+         * method name.
50a3de5
+         *
50a3de5
+         * leaves last_separator pointing to the beginning of the
50a3de5
+         * last package separator (either ' or ::) or 0
50a3de5
+         * if none was found.
50a3de5
+         *
50a3de5
+         * leaves name pointing at the beginning of the
50a3de5
+         * method name.
50a3de5
+         */
50a3de5
+        const char *name_cursor = name;
50a3de5
+        const char * const name_em1 = name_end - 1; /* name_end minus 1 */
50a3de5
+        for (name_cursor = name; name_cursor < name_end ; name_cursor++) {
50a3de5
+            if (*name_cursor == '\'') {
50a3de5
+                last_separator = name_cursor;
50a3de5
+                name = name_cursor + 1;
50a3de5
+            }
50a3de5
+            else if (name_cursor < name_em1 && *name_cursor == ':' && name_cursor[1] == ':') {
50a3de5
+                last_separator = name_cursor++;
50a3de5
+                name = name_cursor + 1;
50a3de5
+            }
50a3de5
+        }
50a3de5
     }
50a3de5
+
50a3de5
+    /* did we find a separator? */
50a3de5
     if (last_separator) {
50a3de5
 	if ((last_separator - origname) == 5 && memEQ(origname, "SUPER", 5)) {
50a3de5
 	    /* ->SUPER::method should really be looked up in original stash */
50a3de5
-- 
50a3de5
2.7.4
50a3de5