baee80
From ea1e86cfdf26a330e58ea377a80273de7110011b Mon Sep 17 00:00:00 2001
baee80
From: Tony Cook <tony@develop-help.com>
baee80
Date: Wed, 21 Aug 2019 11:37:58 +1000
baee80
Subject: [PATCH] disallow vstring magic strings over 2GB-1
baee80
MIME-Version: 1.0
baee80
Content-Type: text/plain; charset=UTF-8
baee80
Content-Transfer-Encoding: 8bit
baee80
baee80
On reads this could result in buffer overflows, so avoid writing
baee80
such large vstrings to avoid causing problems for older Storable.
baee80
baee80
Since we no longer write such large vstrings, we don't want to accept
baee80
them.
baee80
baee80
I doubt that restricting versions strings to under 2GB-1 will have
baee80
a practical effect on downstream users.
baee80
baee80
fixes #17306
baee80
baee80
Signed-off-by: Petr Písař <ppisar@redhat.com>
baee80
---
baee80
 dist/Storable/Storable.xs | 19 ++++++++++++++++---
baee80
 1 file changed, 16 insertions(+), 3 deletions(-)
baee80
baee80
diff --git a/dist/Storable/Storable.xs b/dist/Storable/Storable.xs
baee80
index c2335680ab..d27ac58012 100644
baee80
--- a/dist/Storable/Storable.xs
baee80
+++ b/dist/Storable/Storable.xs
baee80
@@ -2628,6 +2628,12 @@ static int store_scalar(pTHX_ stcxt_t *cxt, SV *sv)
baee80
             /* The macro passes this by address, not value, and a lot of
baee80
                called code assumes that it's 32 bits without checking.  */
baee80
             const SSize_t len = mg->mg_len;
baee80
+            /* we no longer accept vstrings over I32_SIZE-1, so don't emit
baee80
+               them, also, older Storables handle them badly.
baee80
+            */
baee80
+            if (len >= I32_MAX) {
baee80
+                CROAK(("vstring too large to freeze"));
baee80
+            }
baee80
             STORE_PV_LEN((const char *)mg->mg_ptr,
baee80
                          len, SX_VSTRING, SX_LVSTRING);
baee80
         }
baee80
@@ -5937,12 +5943,19 @@ static SV *retrieve_lvstring(pTHX_ stcxt_t *cxt, const char *cname)
baee80
 {
baee80
 #ifdef SvVOK
baee80
     char *s;
baee80
-    I32 len;
baee80
+    U32 len;
baee80
     SV *sv;
baee80
 
baee80
     RLEN(len);
baee80
-    TRACEME(("retrieve_lvstring (#%d), len = %" IVdf,
baee80
-             (int)cxt->tagnum, (IV)len));
baee80
+    TRACEME(("retrieve_lvstring (#%d), len = %" UVuf,
baee80
+             (int)cxt->tagnum, (UV)len));
baee80
+
baee80
+    /* Since we'll no longer produce such large vstrings, reject them
baee80
+       here too.
baee80
+    */
baee80
+    if (len >= I32_MAX) {
baee80
+        CROAK(("vstring too large to fetch"));
baee80
+    }
baee80
 
baee80
     New(10003, s, len+1, char);
baee80
     SAFEPVREAD(s, len, s);
baee80
-- 
baee80
2.21.0
baee80