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