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