683572
From 89f69032d6a71f41b96ae6becbf3df4e2f9509a5 Mon Sep 17 00:00:00 2001
683572
From: Karl Williamson <khw@cpan.org>
683572
Date: Sat, 27 Apr 2019 13:56:39 -0600
683572
Subject: [PATCH] S_scan_const() Properly test if need to grow
683572
MIME-Version: 1.0
683572
Content-Type: text/plain; charset=UTF-8
683572
Content-Transfer-Encoding: 8bit
683572
683572
As we parse the input, creating a string constant, we may have to grow
683572
the destination if it fills up as we go along.  It allocates space in an
683572
SV and populates the string, but it doesn' update the SvCUR until the
683572
end, so in single stepping the debugger through the code, the SV looks
683572
empty until the end.  It turns out that as a result SvEND also doesn't
683572
get updated and still points to the beginning of the string until SvCUR
683572
is finally set.  That means that the test changed by this commit was
683572
always succeeding, because it was using SvEND that didn't get updated,
683572
so it would attempt to grow each time through the loop.  By moving a
683572
couple of statements earlier, and using SvLEN instead, which does always
683572
have the correct value, those extra growth attempts are avoided.
683572
683572
Signed-off-by: Petr Písař <ppisar@redhat.com>
683572
---
683572
 toke.c | 10 ++++++----
683572
 1 file changed, 6 insertions(+), 4 deletions(-)
683572
683572
diff --git a/toke.c b/toke.c
683572
index 68eea0cae6..03c4f2ba26 100644
683572
--- a/toke.c
683572
+++ b/toke.c
683572
@@ -4097,10 +4097,12 @@ S_scan_const(pTHX_ char *start)
683572
             goto default_action; /* Redo, having upgraded so both are UTF-8 */
683572
         }
683572
         else {  /* UTF8ness matters: convert this non-UTF8 source char to
683572
-                   UTF-8 for output.  It will occupy 2 bytes */
683572
-            if (d + 2 >= SvEND(sv)) {
683572
-                const STRLEN extra = 2 + (send - s - 1) + 1;
683572
-		const STRLEN off = d - SvPVX_const(sv);
683572
+                   UTF-8 for output.  It will occupy 2 bytes, but don't include
683572
+                   the input byte since we haven't incremented 's' yet. See
683572
+                   Note on sizing above. */
683572
+            const STRLEN off = d - SvPVX(sv);
683572
+            const STRLEN extra = 2 + (send - s - 1) + 1;
683572
+            if (off + extra > SvLEN(sv)) {
683572
 		d = off + SvGROW(sv, off + extra);
683572
 	    }
683572
             *d++ = UTF8_EIGHT_BIT_HI(*s);
683572
-- 
683572
2.20.1
683572