Skip to content

Commit 738155d

Browse files
author
Father Chrysostomos
committed
[perl #128187] Forbid keys @_ in assigned lv sub
This is a continuation of this commit’s great grandparent, extending the error to arrays.
1 parent 65985bd commit 738155d

File tree

6 files changed

+23
-8
lines changed

6 files changed

+23
-8
lines changed

lib/B/Op_private.pm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ $bits{$_}{6} = 'OPpLVAL_DEFER' for qw(aelem helem multideref);
136136
$bits{$_}{7} = 'OPpLVAL_INTRO' for qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multideref padav padhv padrange padsv pushmark refassign rv2av rv2gv rv2hv rv2sv);
137137
$bits{$_}{2} = 'OPpLVREF_ELEM' for qw(lvref refassign);
138138
$bits{$_}{3} = 'OPpLVREF_ITER' for qw(lvref refassign);
139-
$bits{$_}{3} = 'OPpMAYBE_LVSUB' for qw(aassign aelem aslice av2arylen helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec);
139+
$bits{$_}{3} = 'OPpMAYBE_LVSUB' for qw(aassign aelem akeys aslice av2arylen helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec);
140140
$bits{$_}{4} = 'OPpMAYBE_TRUEBOOL' for qw(padhv rv2hv);
141141
$bits{$_}{7} = 'OPpOFFBYONE' for qw(caller runcv wantarray);
142142
$bits{$_}{5} = 'OPpOPEN_IN_CRLF' for qw(backtick open);
@@ -772,7 +772,7 @@ our %ops_using = (
772772
OPpLVAL_DEFER => [qw(aelem helem multideref)],
773773
OPpLVAL_INTRO => [qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multideref padav padhv padrange padsv pushmark refassign rv2av rv2gv rv2hv rv2sv)],
774774
OPpLVREF_ELEM => [qw(lvref refassign)],
775-
OPpMAYBE_LVSUB => [qw(aassign aelem aslice av2arylen helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec)],
775+
OPpMAYBE_LVSUB => [qw(aassign aelem akeys aslice av2arylen helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec)],
776776
OPpMAYBE_TRUEBOOL => [qw(padhv rv2hv)],
777777
OPpMULTIDEREF_DELETE => [qw(multideref)],
778778
OPpOFFBYONE => [qw(caller runcv wantarray)],

op.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,6 +2977,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
29772977
break;
29782978
case OP_KVHSLICE:
29792979
case OP_KVASLICE:
2980+
case OP_AKEYS:
29802981
if (type == OP_LEAVESUBLV)
29812982
o->op_private |= OPpMAYBE_LVSUB;
29822983
goto nomod;

opcode.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,7 +2557,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = {
25572557
96, /* aslice */
25582558
99, /* kvaslice */
25592559
0, /* aeach */
2560-
0, /* akeys */
2560+
39, /* akeys */
25612561
0, /* avalues */
25622562
0, /* each */
25632563
0, /* values */
@@ -2826,7 +2826,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = {
28262826
*/
28272827

28282828
EXTCONST U16 PL_op_private_bitdefs[] = {
2829-
0x0003, /* scalar, prototype, refgen, srefgen, ref, readline, regcmaybe, regcreset, regcomp, chop, schop, defined, undef, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, negate, i_negate, not, complement, ucfirst, lcfirst, uc, lc, quotemeta, aeach, akeys, avalues, each, values, pop, shift, grepstart, grepwhile, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, method, method_named, method_super, method_redir, method_redir_super, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, fc, anonconst */
2829+
0x0003, /* scalar, prototype, refgen, srefgen, ref, readline, regcmaybe, regcreset, regcomp, chop, schop, defined, undef, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, negate, i_negate, not, complement, ucfirst, lcfirst, uc, lc, quotemeta, aeach, avalues, each, values, pop, shift, grepstart, grepwhile, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, method, method_named, method_super, method_redir, method_redir_super, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, fc, anonconst */
28302830
0x2b5c, 0x3d59, /* pushmark */
28312831
0x00bd, /* wantarray, runcv */
28322832
0x03b8, 0x17f0, 0x3e0c, 0x38c8, 0x2f25, /* const */
@@ -2839,7 +2839,7 @@ EXTCONST U16 PL_op_private_bitdefs[] = {
28392839
0x3819, /* pushre, match, qr, subst */
28402840
0x2b5c, 0x19d8, 0x0256, 0x2c4c, 0x2e48, 0x3e04, 0x0003, /* rv2gv */
28412841
0x2b5c, 0x3078, 0x0256, 0x3e04, 0x0003, /* rv2sv */
2842-
0x2c4c, 0x0003, /* av2arylen, pos, keys */
2842+
0x2c4c, 0x0003, /* av2arylen, pos, akeys, keys */
28432843
0x2dbc, 0x0e18, 0x0b74, 0x028c, 0x3fc8, 0x3e04, 0x0003, /* rv2cv */
28442844
0x012f, /* bless, glob, sprintf, formline, unpack, pack, join, anonlist, anonhash, splice, warn, die, reset, exit, close, pipe_op, fileno, umask, binmode, tie, dbmopen, sselect, select, getc, read, enterwrite, sysopen, sysseek, sysread, syswrite, eof, tell, seek, truncate, fcntl, ioctl, send, recv, socket, sockpair, bind, connect, listen, accept, shutdown, gsockopt, ssockopt, open_dir, seekdir, gmtime, shmget, shmctl, shmread, shmwrite, msgget, msgctl, msgsnd, msgrcv, semop, semget, semctl, ghbyaddr, gnbyaddr, gpbynumber, gsbyname, gsbyport, syscall */
28452845
0x325c, 0x3178, 0x2634, 0x2570, 0x0003, /* backtick */
@@ -3038,7 +3038,7 @@ EXTCONST U8 PL_op_private_valid[] = {
30383038
/* ASLICE */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpLVAL_INTRO),
30393039
/* KVASLICE */ (OPpMAYBE_LVSUB),
30403040
/* AEACH */ (OPpARG1_MASK),
3041-
/* AKEYS */ (OPpARG1_MASK),
3041+
/* AKEYS */ (OPpARG1_MASK|OPpMAYBE_LVSUB),
30423042
/* AVALUES */ (OPpARG1_MASK),
30433043
/* EACH */ (OPpARG1_MASK),
30443044
/* VALUES */ (OPpARG1_MASK),

pp.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,6 +4832,14 @@ PP(pp_akeys)
48324832
PUSHi(av_tindex(array) + 1);
48334833
}
48344834
else if (gimme == G_ARRAY) {
4835+
if (UNLIKELY(PL_op->op_private & OPpMAYBE_LVSUB)) {
4836+
const I32 flags = is_lvalue_sub();
4837+
if (flags && !(flags & OPpENTERSUB_INARGS))
4838+
/* diag_listed_as: Can't modify %s in %s */
4839+
Perl_croak(aTHX_
4840+
"Can't modify keys on array in list assignment");
4841+
}
4842+
{
48354843
IV n = Perl_av_len(aTHX_ array);
48364844
IV i;
48374845

@@ -4848,6 +4856,7 @@ PP(pp_akeys)
48484856
PUSHs(elem ? *elem : &PL_sv_undef);
48494857
}
48504858
}
4859+
}
48514860
}
48524861
RETURN;
48534862
}

regen/op_private

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ addbits($_, 6 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our()
437437
# We might be an lvalue to return
438438
addbits($_, 3 => qw(OPpMAYBE_LVSUB LVSUB))
439439
for qw(aassign rv2av rv2gv rv2hv padav padhv aelem helem aslice hslice
440-
av2arylen keys kvaslice kvhslice substr pos vec multideref);
440+
av2arylen keys akeys kvaslice kvhslice substr pos vec
441+
multideref);
441442

442443

443444

t/op/sub_lval.t

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ BEGIN {
55
@INC = '../lib';
66
require './test.pl';
77
}
8-
plan tests=>210;
8+
plan tests=>211;
99

1010
sub a : lvalue { my $a = 34; ${\(bless \$a)} } # Return a temporary
1111
sub b : lvalue { ${\shift} }
@@ -556,6 +556,10 @@ is scalar %__, '1/64', 'keys assignment through lvalue sub';
556556
eval { (keeze) = 64 };
557557
like $@, qr/^Can't modify keys in list assignment at /,
558558
'list assignment to keys through lv sub is forbidden';
559+
sub akeeze : lvalue { keys @_ }
560+
eval { (akeeze) = 64 };
561+
like $@, qr/^Can't modify keys on array in list assignment at /,
562+
'list assignment to keys @_ through lv sub is forbidden';
559563

560564
# Bug 20001223.002: split thought that the list had only one element
561565
@ary = qw(4 5 6);

0 commit comments

Comments
 (0)