In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/f62fd06d790b3f8da5a193403a316ebbea86ba52?hp=c3d9aeb96afe725795daceaf39f6b133c0593328>

- Log -----------------------------------------------------------------
commit f62fd06d790b3f8da5a193403a316ebbea86ba52
Author: David Mitchell <da...@iabyn.com>
Date:   Sat Feb 18 10:20:00 2017 +0000

    pp_formline(): avoid buffer overrun
    
    RT #130703
    
    My recent commit v5.25.9-77-g90c3aa0 attempted to simplify buffer growth
    in pp_formline(), but missed the operators which append data to
    PL_formtarget *without* doing 'goto append'. These ops either append a
    fieldsize's worth of bytes, or a \n (FF_NEWLINE). So grow by fieldsize
    whenever we fetch something new, and for each FF_NEWLINE.
-----------------------------------------------------------------------

Summary of changes:
 pp_ctl.c     | 11 +++++++++++
 t/op/write.t | 15 ++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/pp_ctl.c b/pp_ctl.c
index 2fcceb2bd2..c4c8bcd0c1 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -566,6 +566,13 @@ PP(pp_formline)
            arg = *fpc++;
            f += arg;
            fieldsize = arg;
+            {
+                STRLEN cur = t - SvPVX_const(PL_formtarget);
+                /* ensure there's always space for the ops which don't
+                 * 'goto append' to unconditionally append a field's
+                 * worth, e.g. FF_SPACE, FF_DECIMAL */
+                t = SvGROW(PL_formtarget, cur + fieldsize + 1) + cur;
+            }
 
            if (MARK < SP)
                sv = *++MARK;
@@ -872,6 +879,10 @@ PP(pp_formline)
        case FF_NEWLINE: /* delete trailing spaces, then append \n */
            f++;
            while (t-- > (SvPVX(PL_formtarget) + linemark) && *t == ' ') ;
+            {
+                STRLEN cur = t - SvPVX_const(PL_formtarget);
+                t = SvGROW(PL_formtarget, cur + 1 + 1) + cur;
+            }
            t++;
            *t++ = '\n';
            break;
diff --git a/t/op/write.t b/t/op/write.t
index 99f827fe0f..d528a8e3f1 100644
--- a/t/op/write.t
+++ b/t/op/write.t
@@ -98,7 +98,7 @@ for my $tref ( @NumTests ){
 my $bas_tests = 21;
 
 # number of tests in section 3
-my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 6 + 2 + 3 + 96 + 11 + 14;
+my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 6 + 2 + 3 + 96 + 11 + 15;
 
 # number of tests in section 4
 my $hmb_tests = 37;
@@ -1577,6 +1577,19 @@ ok  defined *{$::{CmT}}{FORMAT}, "glob assign";
         is $^A, $expected, "RT #130703";
     }
 
+    # further buffer overflows with RT #130703
+
+    {
+        local $^A = '';
+        my $n = 200;
+        my $long = 'x' x 300;
+        my $numf = ('@###' x $n);
+        my $expected = $long . "\n" . ("   1" x $n);
+        formline("@*\n$numf", $long, ('1') x $n);
+
+        is $^A, $expected, "RT #130703 part 2";
+    }
+
 
     # make sure it can cope with formats > 64k
 

--
Perl5 Master Repository

Reply via email to