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