This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
hash keys: validate hash key length at compile time
authorTony Cook <tony@develop-help.com>
Thu, 13 Jul 2023 01:01:46 +0000 (11:01 +1000)
committerTony Cook <tony@develop-help.com>
Thu, 27 Jul 2023 03:58:54 +0000 (13:58 +1000)
This was new to me, I hadn't encountered this failure while working
on the original "other I32 bugs".

The original test here was failing with an "Out of memory" error
since the long hash key length was overflowing the I32.

Once that was fixed the test was failing purely due to the invalid
code, once that was fixed the test passed so I removed the TODO.

op.c
t/bigmem/hash.t

diff --git a/op.c b/op.c
index e64fc01..8812d6b 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2742,7 +2742,11 @@ Perl_check_hash_fields_and_hekify(pTHX_ UNOP *rop, SVOP *key_op, int real)
         {
             SSize_t keylen;
             const char * const key = SvPV_const(sv, *(STRLEN*)&keylen);
-            SV *nsv = newSVpvn_share(key, SvUTF8(sv) ? -keylen : keylen, 0);
+            if (keylen > I32_MAX) {
+                Perl_croak_nocontext("Sorry, hash keys must be smaller than 2**31 bytes");
+            }
+
+            SV *nsv = newSVpvn_share(key, SvUTF8(sv) ? -(I32)keylen : (I32)keylen, 0);
             SvREFCNT_dec_NN(sv);
             *svp = nsv;
         }
index e3d2980..c56f342 100644 (file)
@@ -25,9 +25,6 @@ like(exn('my $h = { "x" x 2**31, undef }'),
      qr/^\QSorry, hash keys must be smaller than 2**31 bytes\E\b/,
      "hash constructed with huge key");
 
-TODO: {
-    local $TODO = "Doesn't yet work with OP_MULTIDEREF";
-    like(exn('my %h; %h{ "x" x 2**31 } = undef'),
-         qr/^\QSorry, hash keys must be smaller than 2**31 bytes\E\b/,
-         "assign to huge hash key");
-}
+like(exn('my %h; $h{ "x" x 2**31 } = undef'),
+     qr/^\QSorry, hash keys must be smaller than 2**31 bytes\E\b/,
+     "assign to huge hash key");