This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: gh#17227 heap-buffer-overflow
authorKarl Williamson <khw@cpan.org>
Fri, 8 Nov 2019 17:29:05 +0000 (10:29 -0700)
committerKarl Williamson <khw@cpan.org>
Fri, 8 Nov 2019 17:40:18 +0000 (10:40 -0700)
There were two problems this uncovered.  One was that a floating point
expression with both operands ints truncated before becoming floating.
One operand needs to be floating.

The second is that the expansion of a non-UTF-8 byte needs to be
considered based on non-UTF-8, rather than its UTF-8 representation.

op.c
t/op/tr_latin1.t

diff --git a/op.c b/op.c
index 593b88a..41824a4 100644 (file)
--- a/op.c
+++ b/op.c
@@ -7336,7 +7336,19 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
                     && r_cp_end != TR_SPECIAL_HANDLING
                     && UVCHR_SKIP(t_cp_end) < UVCHR_SKIP(r_cp_end))
                 {
-                    NV ratio = UVCHR_SKIP(r_cp_end) / UVCHR_SKIP(t_cp);
+                    /* Consider tr/\xCB/\X{E000}/.  The maximum expansion
+                     * factor is 1 byte going to 3 if the lhs is not UTF-8, but
+                     * 2 bytes going to 3 if it is in UTF-8.  We could pass two
+                     * different values so doop could choose based on the
+                     * UTF-8ness of the target.  But khw thinks (perhaps
+                     * wrongly) that is overkill.  It is used only to make sure
+                     * we malloc enough space.  If no target string can force
+                     * the result to be UTF-8, then we don't have to worry
+                     * about this */
+                    NV t_size = (can_force_utf8 && t_cp < 256)
+                                ? 1
+                                : UVCHR_SKIP(t_cp_end);
+                    NV ratio = UVCHR_SKIP(r_cp_end) / t_size;
 
                     o->op_private |= OPpTRANS_GROWS;
 
index 3cfe6f9..9d08652 100644 (file)
@@ -7,7 +7,7 @@ BEGIN {
     set_up_inc('../lib');
 }
 
-plan tests => 1;
+plan tests => 2;
 
 { # 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
@@ -18,4 +18,9 @@ plan tests => 1;
 
 }
 
+{   # gh#17277.  This caused errors with valgrind and asan
+    fresh_perl_is('no warnings qw(void uninitialized); s~~00~-y~Ë0~\x{E00}~',
+                  "", {}, 'gh#17227');
+}
+
 1;