Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strict refs doesn't catch symbolic bareword filehandles #15106

Open
p5pRT opened this issue Dec 28, 2015 · 5 comments
Open

strict refs doesn't catch symbolic bareword filehandles #15106

p5pRT opened this issue Dec 28, 2015 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 28, 2015

Migrated from rt.perl.org#127061 (status was 'open')

Searchable as RT127061$

@p5pRT
Copy link
Author

p5pRT commented Dec 28, 2015

From @mauke

Created by @mauke

$ perl -we 'use strict; @​ARGV = "echo wtf |"; my $fh = "ARGV"; while (<$fh>) { print }'
wtf

I would have expected strict 'refs' to disallow symbolic access to bareword
filehandles, but apparently it doesn't. (In certain CGI related situations this
can lead to security problems if the attacker also controls @​ARGV.)

Can we fix strict to disallow strings in readline/tell/close/etc?

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.22.0:

Configured by mauke at Sat Jul  4 14:56:57 CEST 2015.

Summary of my perl5 (revision 5 version 22 subversion 0) configuration:
   
  Platform:
    osname=linux, osvers=4.0.1-1-arch, archname=i686-linux
    uname='linux simplicio 4.0.1-1-arch #1 smp preempt wed apr 29 12:15:20 cest 2015 i686 gnulinux '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='5.1.0', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234, doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12, longdblkind=3
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/i686-pc-linux-gnu/5.1.0/include-fixed /usr/lib /lib
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.21.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.21'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'



@INC for perl 5.22.0:
    /home/mauke/usr/lib/perl5/site_perl/5.22.0/i686-linux
    /home/mauke/usr/lib/perl5/site_perl/5.22.0
    /home/mauke/usr/lib/perl5/5.22.0/i686-linux
    /home/mauke/usr/lib/perl5/5.22.0
    .


Environment for perl 5.22.0:
    HOME=/home/mauke
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=POSIX
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/mauke/perl5/perlbrew/bin:/home/mauke/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
    PERLBREW_BASHRC_VERSION=0.69
    PERLBREW_HOME=/home/mauke/.perlbrew
    PERLBREW_ROOT=/home/mauke/perl5/perlbrew
    PERL_BADLANG (unset)
    PERL_UNICODE=SAL
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 13, 2016

From @tonycoz

On Mon Dec 28 13​:26​:43 2015, mauke- wrote​:

$ perl -we 'use strict; @​ARGV = "echo wtf |"; my $fh = "ARGV"; while
(<$fh>) { print }'
wtf

I would have expected strict 'refs' to disallow symbolic access to
bareword
filehandles, but apparently it doesn't. (In certain CGI related
situations this
can lead to security problems if the attacker also controls @​ARGV.)

Can we fix strict to disallow strings in readline/tell/close/etc?

Similarly​:

./perl -Ilib -Mstrict -le 'my $foo = "bar"; print defined *$foo'

doesn't prevent access.

I think this needs two changes​:

1) change the order of the checks in S_rv2gv to perform the strict check first

2) change the readline operator to record strictness in op_private

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 13, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2016

From @tonycoz

On Tue Jan 12 21​:47​:14 2016, tonyc wrote​:

I think this needs two changes​:

1) change the order of the checks in S_rv2gv to perform the strict
check first

2) change the readline operator to record strictness in op_private

Patch attached (which shouldn't be applied)

This causes the following test failures​:

Test Summary Report


op/readline.t (Wstat​: 65280 Tests​: 25 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: Bad plan. You planned 32 tests but ran 25.
op/concat2.t (Wstat​: 0 Tests​: 3 Failed​: 1)
  Failed test​: 1
uni/latin2.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
uni/greek.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
uni/tr_7jis.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
uni/tr_sjis.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
uni/tr_eucjp.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
uni/tr_utf8.t (Wstat​: 65280 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: No plan found in TAP output
uni/chr.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
porting/regen.t (Wstat​: 6400 Tests​: 39 Failed​: 0)
  Non-zero exit status​: 25
  Parse errors​: Bad plan. You planned 43 tests but ran 39.
../cpan/Encode/t/enc_data.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
../cpan/Encode/t/enc_eucjp.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
../cpan/Encode/t/enc_module.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: No plan found in TAP output
../cpan/Encode/t/enc_utf8.t (Wstat​: 65280 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: No plan found in TAP output
../cpan/Encode/t/encoding.t (Wstat​: 65280 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: No plan found in TAP output
../cpan/Encode/t/jperl.t (Wstat​: 512 Tests​: 0 Failed​: 0)
  Non-zero exit status​: 2
  Parse errors​: Bad plan. You planned 15 tests but ran 0.
../ext/POSIX/t/sysconf.t (Wstat​: 65280 Tests​: 26 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: Bad plan. You planned 47 tests but ran 26.
../cpan/autodie/t/Fatal.t (Wstat​: 65280 Tests​: 3 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: Bad plan. You planned 17 tests but ran 3.
../cpan/autodie/t/fileno.t (Wstat​: 65280 Tests​: 2 Failed​: 0)
  Non-zero exit status​: 255
  Parse errors​: Bad plan. You planned 8 tests but ran 2.
../lib/strict.t (Wstat​: 0 Tests​: 139 Failed​: 1)
  Failed test​: 81
Files=2407, Tests=748949, 375 wallclock secs (171.79 usr 12.16 sys + 942.99 cusr 26.89 csys = 1153.83 CPU)
Result​: FAIL

I hate to think how much of CPAN it would break.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2016

From @tonycoz

0001-perl-127061-make-foo-enforce-strictness-on-foo-as-a-.patch
From 109d353880bf6a3b72cb3e5726347f66a2a1aab5 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Thu, 14 Jan 2016 11:41:43 +1100
Subject: [perl #127061] make <$foo> enforce strictness on $foo as a globref

This makes many tests fail.
---
 lib/B/Op_private.pm |   4 +-
 op.c                |   3 +
 opcode.h            | 299 ++++++++++++++++++++++++++--------------------------
 pp.c                |  16 +--
 regen/op_private    |   2 +-
 5 files changed, 164 insertions(+), 160 deletions(-)

diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm
index 66166c8..3ad13cc 100644
--- a/lib/B/Op_private.pm
+++ b/lib/B/Op_private.pm
@@ -128,7 +128,7 @@ $bits{$_}{1} = 'OPpFT_ACCESS' for qw(fteexec fteread ftewrite ftrexec ftrread ft
 $bits{$_}{4} = 'OPpFT_AFTER_t' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
 $bits{$_}{2} = 'OPpFT_STACKED' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
 $bits{$_}{3} = 'OPpFT_STACKING' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
-$bits{$_}{1} = 'OPpHINT_STRICT_REFS' for qw(entersub multideref rv2av rv2cv rv2gv rv2hv rv2sv);
+$bits{$_}{1} = 'OPpHINT_STRICT_REFS' for qw(entersub multideref readline rv2av rv2cv rv2gv rv2hv rv2sv);
 $bits{$_}{5} = 'OPpHUSH_VMSISH' for qw(dbstate nextstate);
 $bits{$_}{2} = 'OPpITER_REVERSED' for qw(enteriter iter);
 $bits{$_}{7} = 'OPpLVALUE' for qw(leave leaveloop);
@@ -763,7 +763,7 @@ our %ops_using = (
     OPpFLIP_LINENUM          => [qw(flip flop)],
     OPpFT_ACCESS             => [qw(fteexec fteread ftewrite ftrexec ftrread ftrwrite)],
     OPpFT_AFTER_t            => [qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero)],
-    OPpHINT_STRICT_REFS      => [qw(entersub multideref rv2av rv2cv rv2gv rv2hv rv2sv)],
+    OPpHINT_STRICT_REFS      => [qw(entersub multideref readline rv2av rv2cv rv2gv rv2hv rv2sv)],
     OPpHUSH_VMSISH           => [qw(dbstate nextstate)],
     OPpITER_DEF              => [qw(enteriter)],
     OPpITER_REVERSED         => [qw(enteriter iter)],
diff --git a/op.c b/op.c
index ee31adc..53426c6 100644
--- a/op.c
+++ b/op.c
@@ -10155,6 +10155,8 @@ Perl_ck_readline(pTHX_ OP *o)
 {
     PERL_ARGS_ASSERT_CK_READLINE;
 
+    o->op_private |= (PL_hints & HINT_STRICT_REFS);
+    
     if (o->op_flags & OPf_KIDS) {
 	 OP *kid = cLISTOPo->op_first;
 	 if (kid->op_type == OP_RV2GV) kid->op_private |= OPpALLOW_FAKE;
@@ -10162,6 +10164,7 @@ Perl_ck_readline(pTHX_ OP *o)
     else {
 	OP * const newop
 	    = newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, PL_argvgv));
+        newop->op_private = o->op_private;
 	op_free(o);
 	return newop;
     }
diff --git a/opcode.h b/opcode.h
index e711e65..5870d21 100644
--- a/opcode.h
+++ b/opcode.h
@@ -2441,7 +2441,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       48, /* bless */
       49, /* backtick */
       48, /* glob */
-       0, /* readline */
+      54, /* readline */
       -1, /* rcatline */
        0, /* regcmaybe */
        0, /* regcreset */
@@ -2449,15 +2449,15 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       26, /* match */
       26, /* qr */
       26, /* subst */
-      54, /* substcont */
-      56, /* trans */
-      56, /* transr */
-      63, /* sassign */
-      66, /* aassign */
+      56, /* substcont */
+      58, /* trans */
+      58, /* transr */
+      65, /* sassign */
+      68, /* aassign */
        0, /* chop */
        0, /* schop */
-      71, /* chomp */
-      71, /* schomp */
+      73, /* chomp */
+      73, /* schomp */
        0, /* defined */
        0, /* undef */
        0, /* study */
@@ -2470,22 +2470,22 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* i_postinc */
        0, /* postdec */
        0, /* i_postdec */
-      73, /* pow */
-      73, /* multiply */
-      73, /* i_multiply */
-      73, /* divide */
-      73, /* i_divide */
-      73, /* modulo */
-      73, /* i_modulo */
-      75, /* repeat */
-      73, /* add */
-      73, /* i_add */
-      73, /* subtract */
-      73, /* i_subtract */
-      73, /* concat */
-      77, /* stringify */
-      73, /* left_shift */
-      73, /* right_shift */
+      75, /* pow */
+      75, /* multiply */
+      75, /* i_multiply */
+      75, /* divide */
+      75, /* i_divide */
+      75, /* modulo */
+      75, /* i_modulo */
+      77, /* repeat */
+      75, /* add */
+      75, /* i_add */
+      75, /* subtract */
+      75, /* i_subtract */
+      75, /* concat */
+      79, /* stringify */
+      75, /* left_shift */
+      75, /* right_shift */
       12, /* lt */
       12, /* i_lt */
       12, /* gt */
@@ -2510,9 +2510,9 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       12, /* bit_and */
       12, /* bit_xor */
       12, /* bit_or */
-      73, /* nbit_and */
-      73, /* nbit_xor */
-      73, /* nbit_or */
+      75, /* nbit_and */
+      75, /* nbit_xor */
+      75, /* nbit_or */
       12, /* sbit_and */
       12, /* sbit_xor */
       12, /* sbit_or */
@@ -2520,110 +2520,110 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* i_negate */
        0, /* not */
        0, /* complement */
-      71, /* ncomplement */
-      71, /* scomplement */
+      73, /* ncomplement */
+      73, /* scomplement */
       12, /* smartmatch */
-      77, /* atan2 */
-      71, /* sin */
-      71, /* cos */
-      77, /* rand */
-      77, /* srand */
-      71, /* exp */
-      71, /* log */
-      71, /* sqrt */
-      71, /* int */
-      71, /* hex */
-      71, /* oct */
-      71, /* abs */
-      71, /* length */
-      79, /* substr */
-      82, /* vec */
-      77, /* index */
-      77, /* rindex */
+      79, /* atan2 */
+      73, /* sin */
+      73, /* cos */
+      79, /* rand */
+      79, /* srand */
+      73, /* exp */
+      73, /* log */
+      73, /* sqrt */
+      73, /* int */
+      73, /* hex */
+      73, /* oct */
+      73, /* abs */
+      73, /* length */
+      81, /* substr */
+      84, /* vec */
+      79, /* index */
+      79, /* rindex */
       48, /* sprintf */
       48, /* formline */
-      71, /* ord */
-      71, /* chr */
-      77, /* crypt */
+      73, /* ord */
+      73, /* chr */
+      79, /* crypt */
        0, /* ucfirst */
        0, /* lcfirst */
        0, /* uc */
        0, /* lc */
        0, /* quotemeta */
-      84, /* rv2av */
-      90, /* aelemfast */
-      90, /* aelemfast_lex */
-      91, /* aelem */
-      96, /* aslice */
-      99, /* kvaslice */
+      86, /* rv2av */
+      92, /* aelemfast */
+      92, /* aelemfast_lex */
+      93, /* aelem */
+      98, /* aslice */
+     101, /* kvaslice */
        0, /* aeach */
        0, /* akeys */
        0, /* avalues */
        0, /* each */
        0, /* values */
       39, /* keys */
-     100, /* delete */
-     103, /* exists */
-     105, /* rv2hv */
-      91, /* helem */
-      96, /* hslice */
-      99, /* kvhslice */
-     113, /* multideref */
+     102, /* delete */
+     105, /* exists */
+     107, /* rv2hv */
+      93, /* helem */
+      98, /* hslice */
+     101, /* kvhslice */
+     115, /* multideref */
       48, /* unpack */
       48, /* pack */
-     120, /* split */
+     122, /* split */
       48, /* join */
-     122, /* list */
+     124, /* list */
       12, /* lslice */
       48, /* anonlist */
       48, /* anonhash */
       48, /* splice */
-      77, /* push */
+      79, /* push */
        0, /* pop */
        0, /* shift */
-      77, /* unshift */
-     124, /* sort */
-     131, /* reverse */
+      79, /* unshift */
+     126, /* sort */
+     133, /* reverse */
        0, /* grepstart */
        0, /* grepwhile */
        0, /* mapstart */
        0, /* mapwhile */
        0, /* range */
-     133, /* flip */
-     133, /* flop */
+     135, /* flip */
+     135, /* flop */
        0, /* and */
        0, /* or */
       12, /* xor */
        0, /* dor */
-     135, /* cond_expr */
+     137, /* cond_expr */
        0, /* andassign */
        0, /* orassign */
        0, /* dorassign */
        0, /* method */
-     137, /* entersub */
-     144, /* leavesub */
-     144, /* leavesublv */
-     146, /* caller */
+     139, /* entersub */
+     146, /* leavesub */
+     146, /* leavesublv */
+     148, /* caller */
       48, /* warn */
       48, /* die */
       48, /* reset */
       -1, /* lineseq */
-     148, /* nextstate */
-     148, /* dbstate */
+     150, /* nextstate */
+     150, /* dbstate */
       -1, /* unstack */
       -1, /* enter */
-     149, /* leave */
+     151, /* leave */
       -1, /* scope */
-     151, /* enteriter */
-     155, /* iter */
+     153, /* enteriter */
+     157, /* iter */
       -1, /* enterloop */
-     156, /* leaveloop */
+     158, /* leaveloop */
       -1, /* return */
-     158, /* last */
-     158, /* next */
-     158, /* redo */
-     158, /* dump */
-     158, /* goto */
+     160, /* last */
+     160, /* next */
+     160, /* redo */
+     160, /* dump */
+     160, /* goto */
       48, /* exit */
        0, /* method_named */
        0, /* method_super */
@@ -2635,7 +2635,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* leavewhen */
       -1, /* break */
       -1, /* continue */
-     160, /* open */
+     162, /* open */
       48, /* close */
       48, /* pipe_op */
       48, /* fileno */
@@ -2651,7 +2651,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       48, /* getc */
       48, /* read */
       48, /* enterwrite */
-     144, /* leavewrite */
+     146, /* leavewrite */
       -1, /* prtf */
       -1, /* print */
       -1, /* say */
@@ -2665,7 +2665,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       48, /* truncate */
       48, /* fcntl */
       48, /* ioctl */
-      77, /* flock */
+      79, /* flock */
       48, /* send */
       48, /* recv */
       48, /* socket */
@@ -2681,45 +2681,45 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* getpeername */
        0, /* lstat */
        0, /* stat */
-     165, /* ftrread */
-     165, /* ftrwrite */
-     165, /* ftrexec */
-     165, /* fteread */
-     165, /* ftewrite */
-     165, /* fteexec */
-     170, /* ftis */
-     170, /* ftsize */
-     170, /* ftmtime */
-     170, /* ftatime */
-     170, /* ftctime */
-     170, /* ftrowned */
-     170, /* fteowned */
-     170, /* ftzero */
-     170, /* ftsock */
-     170, /* ftchr */
-     170, /* ftblk */
-     170, /* ftfile */
-     170, /* ftdir */
-     170, /* ftpipe */
-     170, /* ftsuid */
-     170, /* ftsgid */
-     170, /* ftsvtx */
-     170, /* ftlink */
-     170, /* fttty */
-     170, /* fttext */
-     170, /* ftbinary */
-      77, /* chdir */
-      77, /* chown */
-      71, /* chroot */
-      77, /* unlink */
-      77, /* chmod */
-      77, /* utime */
-      77, /* rename */
-      77, /* link */
-      77, /* symlink */
+     167, /* ftrread */
+     167, /* ftrwrite */
+     167, /* ftrexec */
+     167, /* fteread */
+     167, /* ftewrite */
+     167, /* fteexec */
+     172, /* ftis */
+     172, /* ftsize */
+     172, /* ftmtime */
+     172, /* ftatime */
+     172, /* ftctime */
+     172, /* ftrowned */
+     172, /* fteowned */
+     172, /* ftzero */
+     172, /* ftsock */
+     172, /* ftchr */
+     172, /* ftblk */
+     172, /* ftfile */
+     172, /* ftdir */
+     172, /* ftpipe */
+     172, /* ftsuid */
+     172, /* ftsgid */
+     172, /* ftsvtx */
+     172, /* ftlink */
+     172, /* fttty */
+     172, /* fttext */
+     172, /* ftbinary */
+      79, /* chdir */
+      79, /* chown */
+      73, /* chroot */
+      79, /* unlink */
+      79, /* chmod */
+      79, /* utime */
+      79, /* rename */
+      79, /* link */
+      79, /* symlink */
        0, /* readlink */
-      77, /* mkdir */
-      71, /* rmdir */
+      79, /* mkdir */
+      73, /* rmdir */
       48, /* open_dir */
        0, /* readdir */
        0, /* telldir */
@@ -2727,22 +2727,22 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* rewinddir */
        0, /* closedir */
       -1, /* fork */
-     174, /* wait */
-      77, /* waitpid */
-      77, /* system */
-      77, /* exec */
-      77, /* kill */
-     174, /* getppid */
-      77, /* getpgrp */
-      77, /* setpgrp */
-      77, /* getpriority */
-      77, /* setpriority */
-     174, /* time */
+     176, /* wait */
+      79, /* waitpid */
+      79, /* system */
+      79, /* exec */
+      79, /* kill */
+     176, /* getppid */
+      79, /* getpgrp */
+      79, /* setpgrp */
+      79, /* getpriority */
+      79, /* setpriority */
+     176, /* time */
       -1, /* tms */
        0, /* localtime */
       48, /* gmtime */
        0, /* alarm */
-      77, /* sleep */
+      79, /* sleep */
       48, /* shmget */
       48, /* shmctl */
       48, /* shmread */
@@ -2757,8 +2757,8 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* require */
        0, /* dofile */
       -1, /* hintseval */
-     175, /* entereval */
-     144, /* leaveeval */
+     177, /* entereval */
+     146, /* leaveeval */
        0, /* entertry */
       -1, /* leavetry */
        0, /* ghbyname */
@@ -2796,17 +2796,17 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
        0, /* lock */
        0, /* once */
       -1, /* custom */
-     181, /* coreargs */
+     183, /* coreargs */
        3, /* runcv */
        0, /* fc */
       -1, /* padcv */
       -1, /* introcv */
       -1, /* clonecv */
-     185, /* padrange */
-     187, /* refassign */
-     193, /* lvref */
-     199, /* lvrefslice */
-     200, /* lvavref */
+     187, /* padrange */
+     189, /* refassign */
+     195, /* lvref */
+     201, /* lvrefslice */
+     202, /* lvavref */
        0, /* anonconst */
 
 };
@@ -2826,7 +2826,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
  */
 
 EXTCONST U16  PL_op_private_bitdefs[] = {
-    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 */
+    0x0003, /* scalar, prototype, refgen, srefgen, ref, 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 */
     0x2b5c, 0x3d59, /* pushmark */
     0x00bd, /* wantarray, runcv */
     0x03b8, 0x17f0, 0x3e0c, 0x38c8, 0x2f25, /* const */
@@ -2843,6 +2843,7 @@ EXTCONST U16  PL_op_private_bitdefs[] = {
     0x2dbc, 0x0e18, 0x0b74, 0x028c, 0x3fc8, 0x3e04, 0x0003, /* rv2cv */
     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 */
     0x325c, 0x3178, 0x2634, 0x2570, 0x0003, /* backtick */
+    0x3e04, 0x0003, /* readline */
     0x3818, 0x0003, /* substcont */
     0x0f1c, 0x1f58, 0x0754, 0x3b8c, 0x22e8, 0x01e4, 0x0141, /* trans, transr */
     0x0d5c, 0x0458, 0x0067, /* sassign */
@@ -2922,7 +2923,7 @@ EXTCONST U8 PL_op_private_valid[] = {
     /* BLESS      */ (OPpARG4_MASK),
     /* BACKTICK   */ (OPpARG1_MASK|OPpOPEN_IN_RAW|OPpOPEN_IN_CRLF|OPpOPEN_OUT_RAW|OPpOPEN_OUT_CRLF),
     /* GLOB       */ (OPpARG4_MASK),
-    /* READLINE   */ (OPpARG1_MASK),
+    /* READLINE   */ (OPpARG1_MASK|OPpHINT_STRICT_REFS),
     /* RCATLINE   */ (0),
     /* REGCMAYBE  */ (OPpARG1_MASK),
     /* REGCRESET  */ (OPpARG1_MASK),
diff --git a/pp.c b/pp.c
index 016023e..0fbe3af 100644
--- a/pp.c
+++ b/pp.c
@@ -267,6 +267,14 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
 		    report_uninit(sv);
 		return &PL_sv_undef;
 	    }
+            if (strict) {
+                Perl_die(aTHX_
+                         PL_no_symref_sv,
+                         sv,
+                         (SvPOKp(sv) && SvCUR(sv)>32 ? "..." : ""),
+                         "a symbol"
+                         );
+            }
 	    if (noinit)
 	    {
 		if (!(sv = MUTABLE_SV(gv_fetchsv_nomg(
@@ -275,14 +283,6 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
 		    return &PL_sv_undef;
 	    }
 	    else {
-		if (strict) {
-                    Perl_die(aTHX_
-                             PL_no_symref_sv,
-                             sv,
-                             (SvPOKp(sv) && SvCUR(sv)>32 ? "..." : ""),
-                             "a symbol"
-                             );
-                }
 		if ((PL_op->op_private & (OPpLVAL_INTRO|OPpDONT_INIT_GV))
 		    == OPpDONT_INIT_GV) {
 		    /* We are the target of a coderef assignment.  Return
diff --git a/regen/op_private b/regen/op_private
index ab63e11..2880099 100644
--- a/regen/op_private
+++ b/regen/op_private
@@ -451,7 +451,7 @@ for (qw(rv2hv padhv)) {
 
 
 addbits($_, 1 => qw(OPpHINT_STRICT_REFS STRICT))
-    for qw(rv2sv rv2av rv2hv rv2gv multideref);
+    for qw(rv2sv rv2av rv2hv rv2gv multideref readline);
 
 
 
-- 
2.1.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants