summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-07-07 16:24:41 +0100
committerDavid Mitchell <davem@iabyn.com>2016-07-07 16:24:41 +0100
commit6fe82bd6d07db28c9792126ff851a29fe013401c (patch)
tree1b6d0d0d6247762e2db12847eaa8a770bbd9060e /sv.c
parent1164fd158dc892739cc9ec8b770081b2770c047f (diff)
downloadperl-6fe82bd6d07db28c9792126ff851a29fe013401c.tar.gz
handle magic in multideref "unit val" var names
[perl #128253] Assert fail in S_find_uninit_var $ perl5240 -we'$ISA[0][0]' Useless use of array element in void context at -e line 1. perl5240: sv.c:16078: S_find_uninit_var: Assertion `is_hv' failed. The code in find_uninit_var() which looks for a variable name associated with an uninitialized value assumed, in the OP_MULTIDEREF branch, that the value was either an index if the op was top-level ($foo[$uninit]), or an array/hash element otherwise (1+$foo[...]). It turns out here's a third possibility: magic. In $ISA[0][0], the first array lookup is in lval context, so it initially autovivifies to undef. Normally it would shortly afterwards be upgraded to a ref to an empty AV, but first ISA set magic for @ISA is invoked. This ends up scanning @ISA and finds an uninit value which it tries to use as a key into the stash cache, triggering an ununit value warning. This commit expands the OP_MULTIDEREF code in find_uninit_var() to handle this third possibility - chiefly by not returning a variable name unless the index var is the same SV as the uninit value. As well as fixing the assert failure in this ticket, it also stops printing an incorrect index in code like this: $ perl -we'my $i = 0; $ISA[$i] = 1' before: .... Use of uninitialized value $i in array element at -e line 1. Use of uninitialized value $i in array element at -e line 1. Recursive inheritance detected in package 'main' at -e line 1. after: .... Use of uninitialized value in array element at -e line 1. Use of uninitialized value in array element at -e line 1. Recursive inheritance detected in package 'main' at -e line 1. @ISA magic still has recursion issues with undef values, as can be seen above. I don't address those issues here. Because of that, I haven't been able to add tests.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/sv.c b/sv.c
index 1e294ddb3d..1b7a283e1e 100644
--- a/sv.c
+++ b/sv.c
@@ -15968,11 +15968,14 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
/* If we were executing OP_MULTIDEREF when the undef warning
* triggered, then it must be one of the index values within
* that triggered it. If not, then the only possibility is that
- * the value retrieved by the last aggregate lookup might be the
+ * the value retrieved by the last aggregate index might be the
* culprit. For the former, we set PL_multideref_pc each time before
* using an index, so work though the item list until we reach
* that point. For the latter, just work through the entire item
* list; the last aggregate retrieved will be the candidate.
+ * There is a third rare possibility: something triggered
+ * magic while fetching an array/hash element. Just display
+ * nothing in this case.
*/
/* the named aggregate, if any */
@@ -16072,7 +16075,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
if ( index_type == MDEREF_INDEX_none
|| (actions & MDEREF_FLAG_last)
- || (last && items == last)
+ || (last && items >= last)
)
break;
@@ -16080,7 +16083,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
} /* while */
if (PL_op == obase) {
- /* index was undef */
+ /* most likely index was undef */
*desc_p = ( (actions & MDEREF_FLAG_last)
&& (obase->op_private
@@ -16091,13 +16094,22 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
: "delete"
: is_hv ? "hash element" : "array element";
assert(index_type != MDEREF_INDEX_none);
- if (index_gv)
- return varname(index_gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE);
- if (index_targ)
- return varname(NULL, '$', index_targ,
+ if (index_gv) {
+ if (GvSV(index_gv) == uninit_sv)
+ return varname(index_gv, '$', 0, NULL, 0,
+ FUV_SUBSCRIPT_NONE);
+ else
+ return NULL;
+ }
+ if (index_targ) {
+ if (PL_curpad[index_targ] == uninit_sv)
+ return varname(NULL, '$', index_targ,
NULL, 0, FUV_SUBSCRIPT_NONE);
- assert(is_hv); /* AV index is an IV and can't be undef */
- /* can a const HV index ever be undef? */
+ else
+ return NULL;
+ }
+ /* If we got to this point it was undef on a const subscript,
+ * so magic probably involved, e.g. $ISA[0]. Give up. */
return NULL;
}