This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: [perl #134067] heap buffer overflow in lexing
authorKarl Williamson <khw@cpan.org>
Sat, 27 Apr 2019 20:04:58 +0000 (14:04 -0600)
committerKarl Williamson <khw@cpan.org>
Fri, 3 May 2019 16:58:50 +0000 (10:58 -0600)
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.

MANIFEST
t/op/tr_latin1.t [new file with mode: 0644]
toke.c

index f058168..bec5b5f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -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 (file)
index 0000000..e01477c
--- /dev/null
@@ -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}Ä\8cÿÿ\80\80-ÿoo', "1", { },
+                    'RT #134067 heap-buffer-overflow in S_scan_const');
+
+}
+
+1;
diff --git a/toke.c b/toke.c
index 5dca9de..b409628 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -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;
                         }