diff options
author | Karl Williamson <khw@cpan.org> | 2019-04-27 14:04:58 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2019-05-03 10:58:50 -0600 |
commit | 3fdfceb306b900b57c3ce5ad662aea091cfb53a6 (patch) | |
tree | b6a6ae82e0d422eb1ba8e1fd7a04178e0b017eb2 | |
parent | abf787ba980b7d12a799dc22b830524bed5e028d (diff) | |
download | perl-3fdfceb306b900b57c3ce5ad662aea091cfb53a6.tar.gz |
PATCH: [perl #134067] heap buffer overflow in lexing
This bug happens under tr///. In some circumstances, a byte is inserted
in the output that wasn't in the input, and it did not check that there
was space available for this character. The result could be a write
after the buffer end.
I suspect that this bug has been there all along, and the blamed commit
rearranged things so that it is more likely to happen; it depends on
needing to malloc in just the wrong place.
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | t/op/tr_latin1.t | 20 | ||||
-rw-r--r-- | toke.c | 12 |
3 files changed, 32 insertions, 1 deletions
@@ -5805,6 +5805,7 @@ t/op/tiehandle.t See if tie for handles works t/op/time.t See if time functions work t/op/time_loop.t Test that very large values don't hang gmtime and localtime. t/op/tr.t See if tr works +t/op/tr_latin1.t See if tr works, but file isn't encoded in UTF-8 t/op/undef.t See if undef works t/op/universal.t See if UNIVERSAL class works t/op/unlink.t See if unlink works diff --git a/t/op/tr_latin1.t b/t/op/tr_latin1.t new file mode 100644 index 0000000000..e01477c422 --- /dev/null +++ b/t/op/tr_latin1.t @@ -0,0 +1,20 @@ +# Tests for tr, but the test file is not utf8. + +BEGIN { + chdir 't' if -d 't'; + require './test.pl'; + set_up_inc('../lib'); +} + +plan tests => 1; + +{ # This test is malloc senstive. Right now on some platforms anyway, space + # for the final \xff needs to be mallocd, and that's what caused the + # problem, because the '-' had already been parsed and was later added + # without making space for it + fresh_perl_is('print "\x8c" =~ y o\x{100}ÄŒÿÿ€€-ÿoo', "1", { }, + 'RT #134067 heap-buffer-overflow in S_scan_const'); + +} + +1; @@ -3194,11 +3194,21 @@ S_scan_const(pTHX_ char *start) && (range_min > 255 || ! convert_unicode) #endif ) { + const STRLEN off = d - SvPVX(sv); + const STRLEN extra = 1 + (send - s) + 1; + char *e; + /* Move the high character one byte to the right; then * insert between it and the range begin, an illegal * byte which serves to indicate this is a range (using * a '-' would be ambiguous). */ - char *e = d++; + + if (off + extra > SvLEN(sv)) { + d = off + SvGROW(sv, off + extra); + max_ptr = d - off + offset_to_max; + } + + e = d++; while (e-- > max_ptr) { *(e + 1) = *e; } |