This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #126443] make sure PL_oldbufptr is preserved in scan_heredoc()
authorTony Cook <tony@develop-help.com>
Tue, 24 Nov 2015 03:52:31 +0000 (14:52 +1100)
committerTony Cook <tony@develop-help.com>
Tue, 24 Nov 2015 03:52:31 +0000 (14:52 +1100)
This is later used to update PL_oldoldbufptr, if the token following
the <<FOO is unexpected this causes S_no_op() to access an invalid
*PL_oldoldbufptr.

t/op/heredoc.t
toke.c

index a239e92..dadf105 100644 (file)
@@ -7,7 +7,7 @@ BEGIN {
 }
 
 use strict;
-plan(tests => 39);
+plan(tests => 40);
 
 
 # heredoc without newline (#65838)
@@ -89,4 +89,13 @@ HEREDOC
         {},
         "long terminator fails correctly"
     );
+
+    # this would read freed memory
+    fresh_perl_like(
+        qq(0<<<<""0\n\n),
+        # valgrind and asan reports an error between these two lines
+        qr/^Number found where operator expected at - line 1, near "<<""0"\s+\(Missing operator/,
+        {},
+        "don't use an invalid oldoldbufptr"
+    );
 }
diff --git a/toke.c b/toke.c
index d665b3d..6d6975c 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -9617,12 +9617,14 @@ S_scan_heredoc(pTHX_ char *s)
     else
     {
       SV *linestr_save;
+      char *oldbufptr_save;
      streaming:
       sv_setpvs(tmpstr,"");   /* avoid "uninitialized" warning */
       term = PL_tokenbuf[1];
       len--;
       linestr_save = PL_linestr; /* must restore this afterwards */
       d = s;                    /* and this */
+      oldbufptr_save = PL_oldbufptr;
       PL_linestr = newSVpvs("");
       PL_bufend = SvPVX(PL_linestr);
       while (1) {
@@ -9639,6 +9641,7 @@ S_scan_heredoc(pTHX_ char *s)
               restore PL_linestr. */
            SvREFCNT_dec_NN(PL_linestr);
            PL_linestr = linestr_save;
+            PL_oldbufptr = oldbufptr_save;
            goto interminable;
        }
        CopLINE_set(PL_curcop, origline);
@@ -9673,6 +9676,7 @@ S_scan_heredoc(pTHX_ char *s)
            PL_linestr = linestr_save;
            PL_linestart = SvPVX(linestr_save);
            PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+            PL_oldbufptr = oldbufptr_save;
            s = d;
            break;
        }