summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2020-07-11 09:26:21 +0200
committerYves Orton <demerphq@gmail.com>2021-02-12 19:21:28 +0100
commitaae087f7cec022be14a17deb95cb2208e16b7891 (patch)
tree00c8f01294cb90d0b7a6a888617f0ad89d6af41c /hv.c
parentd18575f18c6ee61ce80492e82cae7361358d570a (diff)
downloadperl-aae087f7cec022be14a17deb95cb2208e16b7891.tar.gz
hv.c: add a guard clause to prevent the number of buckets in a hash from getting too large
This caps it at 1<<28 buckets, eg, ~268M. In theory without a guard clause like this we could grow to the point of possibly wrapping around in terms of size, not to mention being ridiculously wasteful of memory at larger sizes. Even this cap is probably too high. It should probably be something like 1<<24.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/hv.c b/hv.c
index 82657cb4e9..f503dae14c 100644
--- a/hv.c
+++ b/hv.c
@@ -38,7 +38,13 @@ holds the key and hash value.
* NOTE if you change this formula so we split earlier than previously
* you MUST change the logic in hv_ksplit()
*/
-#define DO_HSPLIT(xhv) ( ((xhv)->xhv_keys + ((xhv)->xhv_keys >> 1)) > (xhv)->xhv_max )
+
+/* MAX_BUCKET_MAX is the maximum max bucket index, at which point we stop growing the
+ * number of buckets,
+ */
+#define MAX_BUCKET_MAX ((1<<26)-1)
+#define DO_HSPLIT(xhv) ( ( ((xhv)->xhv_keys + ((xhv)->xhv_keys >> 1)) > (xhv)->xhv_max ) && \
+ ((xhv)->xhv_max < MAX_BUCKET_MAX) )
static const char S_strtab_error[]
= "Cannot modify shared string table in hv_%s";
@@ -1424,6 +1430,8 @@ S_hsplit(pTHX_ HV *hv, STRLEN const oldsize, STRLEN newsize)
);
PERL_ARGS_ASSERT_HSPLIT;
+ if (newsize > MAX_BUCKET_MAX+1)
+ return;
PL_nomemok = TRUE;
Renew(a, PERL_HV_ARRAY_ALLOC_BYTES(newsize)