Blob Blame History Raw
From c5eed6e541fe27d9e9dfd31f42c43f4dfa1f486b Mon Sep 17 00:00:00 2001
From: Yves Orton <demerphq@gmail.com>
Date: Sat, 11 Jul 2020 09:26:21 +0200
Subject: [PATCH] hv.c: add a guard clause to prevent the number of buckets in
 a hash from getting too large
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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.

Petr Písař: Ported to 5.32.1 from
aae087f7cec022be14a17deb95cb2208e16b7891.

Signed-off-by: Petr Písař <ppisar@redhat.com>
---
 hv.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/hv.c b/hv.c
index eccae62..32dbd19 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) )
 #define HV_FILL_THRESHOLD 31
 
 static const char S_strtab_error[]
@@ -1426,6 +1432,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)
-- 
2.26.2