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