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