78f1eb
From 28eabf1185634216ca335b3a24e1131b0f392ca1 Mon Sep 17 00:00:00 2001
78f1eb
From: David Mitchell <davem@iabyn.com>
78f1eb
Date: Wed, 10 Jul 2019 12:59:06 +0100
78f1eb
Subject: [PATCH] avoid SEGV with uninit warning with multideref
78f1eb
MIME-Version: 1.0
78f1eb
Content-Type: text/plain; charset=UTF-8
78f1eb
Content-Transfer-Encoding: 8bit
78f1eb
78f1eb
RT #134275
78f1eb
78f1eb
When the 'uninitialized warning' code in S_find_uninit_var() comes
78f1eb
across an OP_MULTIDEREF node, it scans it to see if any part of that op
78f1eb
(e.g. the indices or the returned value) could have been the source of
78f1eb
the uninitialized value which triggered the warning.  Unfortunately when
78f1eb
getting an AV or HV from a GV, it wasn't checking whether gp_av/gp_hv
78f1eb
contained a NULL value. If so, it would SEGV.
78f1eb
78f1eb
The test code is a bit contrived; you have to "pull the rug" from under
78f1eb
the GV at just the right moment with *foo = *bar, then trigger an uninit
78f1eb
warning on an op whose subtree includes an OP_MULTIDEREF.
78f1eb
78f1eb
Signed-off-by: Petr Písař <ppisar@redhat.com>
78f1eb
---
78f1eb
 sv.c                   |  5 ++++-
78f1eb
 t/lib/warnings/9uninit | 10 ++++++++++
78f1eb
 2 files changed, 14 insertions(+), 1 deletion(-)
78f1eb
78f1eb
diff --git a/sv.c b/sv.c
78f1eb
index 83de536ad7..4315fe9b64 100644
78f1eb
--- a/sv.c
78f1eb
+++ b/sv.c
78f1eb
@@ -16662,8 +16662,11 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
78f1eb
 
78f1eb
         if (agg_targ)
78f1eb
 	    sv = PAD_SV(agg_targ);
78f1eb
-        else if (agg_gv)
78f1eb
+        else if (agg_gv) {
78f1eb
             sv = is_hv ? MUTABLE_SV(GvHV(agg_gv)) : MUTABLE_SV(GvAV(agg_gv));
78f1eb
+            if (!sv)
78f1eb
+                break;
78f1eb
+            }
78f1eb
         else
78f1eb
             break;
78f1eb
 
78f1eb
diff --git a/t/lib/warnings/9uninit b/t/lib/warnings/9uninit
78f1eb
index 774c6ee432..5c173fdb2a 100644
78f1eb
--- a/t/lib/warnings/9uninit
78f1eb
+++ b/t/lib/warnings/9uninit
78f1eb
@@ -2206,3 +2206,13 @@ use warnings 'uninitialized';
78f1eb
 undef $0;
78f1eb
 EXPECT
78f1eb
 Use of uninitialized value in undef operator at - line 5.
78f1eb
+########
78f1eb
+# RT #134275
78f1eb
+# This was SEGVing due to the multideref code in S_find_uninit_var not
78f1eb
+# handling a GV with a null gp_hv slot.
78f1eb
+use warnings 'uninitialized';
78f1eb
+"" =~ /$foo{a}${*foo=*bar}$x/;
78f1eb
+EXPECT
78f1eb
+Use of uninitialized value in regexp compilation at - line 5.
78f1eb
+Use of uninitialized value in regexp compilation at - line 5.
78f1eb
+Use of uninitialized value $x in regexp compilation at - line 5.
78f1eb
-- 
78f1eb
2.20.1
78f1eb