diff options
author | Aaron Crane <arc@cpan.org> | 2017-06-01 14:42:22 +0200 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2017-06-01 17:17:34 +0200 |
commit | b02f36453d1392e2b0bd62fdde2b286fb60bd5bc (patch) | |
tree | 511763b834e942d731ea762309284dccbd5450d0 /embed.fnc | |
parent | 1cf41740f284a4e05bbefc5b15c5ffd9c254aa78 (diff) | |
download | perl-b02f36453d1392e2b0bd62fdde2b286fb60bd5bc.tar.gz |
RT #127742: Hash keys are limited to 2 GB - throw an exception if hash keys are too long
We currently require hash keys to be less than 2**31 bytes long. But (a)
nothing actually tries to enforce that, and (b) if a Perl program tries to
create a hash with such a key (using a 64-bit system), we miscalculate the
size of a memory block, yielding a panic:
$ ./perl -e '+{ "x" x 2**31, undef }'
panic: malloc, size=18446744071562068026 at -e line 1.
Instead, check for this situation, and croak with an appropriate (new)
diagnostic in the unlikely event that it occurs.
This also involves changing the type of an argument to a public API function:
Perl_share_hek() previously took the key's length as an I32, but that makes
it impossible to detect over-long keys, so it must be SSize_t instead.
From Yves:
We also inject the length test into the PERL_HASH() macro, so that where
the macro is used *before* calling into any of the hv functions we can
avoid hashing a very long string only to throw an exception that it is
too long. Might as well fail fast.
Diffstat (limited to 'embed.fnc')
-rw-r--r-- | embed.fnc | 4 |
1 files changed, 2 insertions, 2 deletions
@@ -1444,7 +1444,7 @@ AMpd |OP* |op_scope |NULLOK OP* o : Only used by perl.c/miniperl.c, but defined in caretx.c px |void |set_caret_X Apd |void |setdefout |NN GV* gv -Ap |HEK* |share_hek |NN const char* str|I32 len|U32 hash +Ap |HEK* |share_hek |NN const char* str|SSize_t len|U32 hash #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) : Used in perl.c np |Signal_t |sighandler |int sig|NULLOK siginfo_t *info|NULLOK void *uap @@ -2072,7 +2072,7 @@ sR |HE* |new_he sanR |HEK* |save_hek_flags |NN const char *str|I32 len|U32 hash|int flags sn |void |hv_magic_check |NN HV *hv|NN bool *needs_copy|NN bool *needs_store s |void |unshare_hek_or_pvn|NULLOK const HEK* hek|NULLOK const char* str|I32 len|U32 hash -sR |HEK* |share_hek_flags|NN const char *str|I32 len|U32 hash|int flags +sR |HEK* |share_hek_flags|NN const char *str|STRLEN len|U32 hash|int flags rs |void |hv_notallowed |int flags|NN const char *key|I32 klen|NN const char *msg in |U32|ptr_hash|PTRV u s |struct xpvhv_aux*|hv_auxinit|NN HV *hv |