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