3f1b01
From c5eed6e541fe27d9e9dfd31f42c43f4dfa1f486b Mon Sep 17 00:00:00 2001
3f1b01
From: Yves Orton <demerphq@gmail.com>
3f1b01
Date: Sat, 11 Jul 2020 09:26:21 +0200
3f1b01
Subject: [PATCH] hv.c: add a guard clause to prevent the number of buckets in
3f1b01
 a hash from getting too large
3f1b01
MIME-Version: 1.0
3f1b01
Content-Type: text/plain; charset=UTF-8
3f1b01
Content-Transfer-Encoding: 8bit
3f1b01
3f1b01
This caps it at 1<<28 buckets, eg, ~268M. In theory without a guard clause like
3f1b01
this we could grow to the point of possibly wrapping around in terms of size,
3f1b01
not to mention being ridiculously wasteful of memory at larger sizes.
3f1b01
Even this cap is probably too high. It should probably be something like 1<<24.
3f1b01
3f1b01
Petr Písař: Ported to 5.32.1 from
3f1b01
aae087f7cec022be14a17deb95cb2208e16b7891.
3f1b01
3f1b01
Signed-off-by: Petr Písař <ppisar@redhat.com>
3f1b01
---
3f1b01
 hv.c | 10 +++++++++-
3f1b01
 1 file changed, 9 insertions(+), 1 deletion(-)
3f1b01
3f1b01
diff --git a/hv.c b/hv.c
3f1b01
index eccae62..32dbd19 100644
3f1b01
--- a/hv.c
3f1b01
+++ b/hv.c
3f1b01
@@ -38,7 +38,13 @@ holds the key and hash value.
3f1b01
  * NOTE if you change this formula so we split earlier than previously
3f1b01
  * you MUST change the logic in hv_ksplit()
3f1b01
  */
3f1b01
-#define DO_HSPLIT(xhv) ( ((xhv)->xhv_keys + ((xhv)->xhv_keys >> 1))  > (xhv)->xhv_max )
3f1b01
+
3f1b01
+/*  MAX_BUCKET_MAX is the maximum max bucket index, at which point we stop growing the
3f1b01
+ *  number of buckets,
3f1b01
+ */
3f1b01
+#define MAX_BUCKET_MAX ((1<<26)-1)
3f1b01
+#define DO_HSPLIT(xhv) ( ( ((xhv)->xhv_keys + ((xhv)->xhv_keys >> 1)) > (xhv)->xhv_max ) && \
3f1b01
+                           ((xhv)->xhv_max < MAX_BUCKET_MAX) )
3f1b01
 #define HV_FILL_THRESHOLD 31
3f1b01
 
3f1b01
 static const char S_strtab_error[]
3f1b01
@@ -1426,6 +1432,8 @@ S_hsplit(pTHX_ HV *hv, STRLEN const oldsize, STRLEN newsize)
3f1b01
     );
3f1b01
 
3f1b01
     PERL_ARGS_ASSERT_HSPLIT;
3f1b01
+    if (newsize > MAX_BUCKET_MAX+1)
3f1b01
+            return;
3f1b01
 
3f1b01
     PL_nomemok = TRUE;
3f1b01
     Renew(a, PERL_HV_ARRAY_ALLOC_BYTES(newsize)
3f1b01
-- 
3f1b01
2.26.2
3f1b01