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