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