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

substr in sub call doesn't respect lexical "no warnings" #14399

Open
p5pRT opened this issue Jan 5, 2015 · 4 comments
Open

substr in sub call doesn't respect lexical "no warnings" #14399

p5pRT opened this issue Jan 5, 2015 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 5, 2015

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

Searchable as RT123552$

@p5pRT
Copy link
Author

p5pRT commented Jan 5, 2015

From michael.j.carman@gmail.com

This is a bug report for perl from michael.j.carman@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.16.1.


When substr is used as an argument to a sub call and the substring is outside of
the string, perl mis-reports the line number and doesn't correctly respect a
lexical "no warnings". e.g.

  use strict;
  use warnings;

  {
  no warnings 'substr'; # no effect
  foo(substr('123', 4, 6)); # warning should be inhibited
  }

  sub foo {
  my $s = shift; # warning reported here
  }

Under v5.16.1 this emits

  substr outside of string at c​:\temp\foo.pl line 10.

In order to suppress the warning the "no warnings 'substr'" line must be moved
inside the body of foo, which is very unintitive.

This behavior appears to be related to changes in v5.16.0 that made a substr
outside of a string less fatal. From perl5160delta​:

  Passing a substring of a read-only value or a typeglob to a function
  (potential lvalue context) no longer causes an immediate "Can't coerce" or
  "Modification of a read-only value" error. That error occurs only if the
  passed value is assigned to.

  The same thing happens with the "substr outside of string" error. If the
  lvalue is only read from, not written to, it is now just a warning, as with
  rvalue substr.

In 5.10.1 the code sample dies on the call to substr but correctly reports the
problem as occuring on line 6.



Flags​:
  category=core
  severity=low


Site configuration information for perl 5.16.1​:

Configured by gecko at Thu Aug 30 20​:04​:55 2012.

Summary of my perl5 (revision 5 version 16 subversion 1) configuration​:

  Platform​:
  osname=MSWin32, osvers=5.2, archname=MSWin32-x86-multi-thread
  uname=''
  config_args='undef'
  hint=recommended, useposix=true, d_sigaction=undef
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=undef, use64bitall=undef, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='C​:\rw_apps\MinGW\bin\gcc.exe', ccflags ='-DNDEBUG -DWIN32
-D_CONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPTS -DUSE_SITECUSTOMIZE
-DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO
-D_USE_32BIT_TIME_T -DHASATTRIBUTE -fno-strict-aliasing
-mms-bitfields',
  optimize='-O2',
  cppflags='-DWIN32'
  ccversion='', gccversion='4.6.2', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8
  ivtype='long', ivsize=4, nvtype='double', nvsize=8,
Off_t='__int64', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='C​:\rw_apps\MinGW\bin\g++.exe', ldflags ='-L"C​:\Perl\5.16.1\lib\CORE"'
  libpth=\lib
  libs=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32
-lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm
-lversion -lodbc32 -lodbccp32 -lcomctl32 -lmsvcrt
  perllibs=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
-ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32
-lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 -lmsvcrt
  libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl516.lib
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags='-mdll -L"C​:\Perl\5.16.1\lib\CORE"'

Locally applied patches​:
  ACTIVEPERL_LOCAL_PATCHES_ENTRY


@​INC for perl 5.16.1​:
  C​:/Perl/5.16.1/site/lib
  C​:/Perl/5.16.1/lib
  .


Environment for perl 5.16.1​:
  HOME (unset)
  LANG (unset)
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=C​:\rw_apps\ConEmu\ConEmu;C​:\rw_apps\ConEmu;C​:\oraclexe\app\oracle\product\11.2.0\server\bin;;C​:\Oracle11g\product\11.2.0\client_1\bin;C​:\Windows\system32;C​:\Windows;C​:\Windows\System32\Wbem;C​:\Windows\System32\WindowsPowerShell\v1.0\;C​:\Program
Files (x86)\Java\jdk1.6.0_43\bin;C​:\oraclexe\app\oracle\product\11.2.0\server\bin;C​:\rw_apps\IBM\RationalSDLC\common;C​:\rw_apps\IBM\RationalSDLC\ClearCase\bin;C​:\Program
Files (x86)\Microsoft Application Virtualization Client;C​:\Program
Files\Adobe\Adobe PDF iFilter 9 for 64-bit platforms\Bin;C​:\Program
Files\TortoiseSVN\bin;C​:\Perl\5.16.1\site\bin;C​:\Perl\5.16.1\bin;C​:\Tools;C​:\rw_apps\MinGW\bin;Z​:\FlexIO\Tools
  PERL5LIB=C​:/Perl/5.16.1/site/lib
  PERL_BADLANG (unset)
  SHELL (unset)

@p5pRT
Copy link
Author

p5pRT commented Jan 6, 2015

From @cpansprout

On Mon Jan 05 11​:44​:51 2015, michael.j.carman@​gmail.com wrote​:

This is a bug report for perl from michael.j.carman@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.16.1.

-----------------------------------------------------------------
When substr is used as an argument to a sub call and the substring is
outside of
the string, perl mis-reports the line number and doesn't correctly
respect a
lexical "no warnings". e.g.

use strict;
use warnings;

{
no warnings 'substr'; # no effect
foo(substr('123', 4, 6)); # warning should be inhibited
}

sub foo {
my $s = shift; # warning reported here
}

Under v5.16.1 this emits

substr outside of string at c​:\temp\foo.pl line 10.

In order to suppress the warning the "no warnings 'substr'" line must
be moved
inside the body of foo, which is very unintitive.

This behavior appears to be related to changes in v5.16.0 that made a
substr
outside of a string less fatal. From perl5160delta​:

Passing a substring of a read-only value or a typeglob to a function
(potential lvalue context) no longer causes an immediate "Can't
coerce" or
"Modification of a read-only value" error. That error occurs only if
the
passed value is assigned to.

The same thing happens with the "substr outside of string" error. If
the
lvalue is only read from, not written to, it is now just a warning, as
with
rvalue substr.

In 5.10.1 the code sample dies on the call to substr but correctly
reports the
problem as occuring on line 6.

I’m not sure there is any way to fix this without breaking other things. You see, the substr() call creates a special magical scalar and that scalar is passed to foo(). It is only when you try to read from that scalar (or assign to it) that perl finds out that it represents a substring outside of the target string.

It is necessary for it to work this way in the case of variables, as in foo(substr($bar, 4, 6)), because the value of $bar may change before the substring is taken.

If we make this work differently for constant targets and variable targets, then we get the warning occurring in different places; it would be less predictable. So it’s six of one or half a dozen of the other.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 6, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Jan 6, 2015

From michael.j.carman@gmail.com

On Mon Jan 05 17​:59​:38 2015, sprout wrote​:

On Mon Jan 05 11​:44​:51 2015, michael.j.carman@​gmail.com wrote​:

This is a bug report for perl from michael.j.carman@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.16.1.

-----------------------------------------------------------------
When substr is used as an argument to a sub call and the substring is
outside of
the string, perl mis-reports the line number and doesn't correctly
respect a
lexical "no warnings". e.g.

use strict;
use warnings;

{
no warnings 'substr'; # no effect
foo(substr('123', 4, 6)); # warning should be inhibited
}

sub foo {
my $s = shift; # warning reported here
}

Under v5.16.1 this emits

substr outside of string at c​:\temp\foo.pl line 10.

In order to suppress the warning the "no warnings 'substr'" line must
be moved
inside the body of foo, which is very unintitive.

This behavior appears to be related to changes in v5.16.0 that made a
substr
outside of a string less fatal. From perl5160delta​:

Passing a substring of a read-only value or a typeglob to a function
(potential lvalue context) no longer causes an immediate "Can't
coerce" or
"Modification of a read-only value" error. That error occurs only if
the
passed value is assigned to.

The same thing happens with the "substr outside of string" error. If
the
lvalue is only read from, not written to, it is now just a warning,
as
with
rvalue substr.

In 5.10.1 the code sample dies on the call to substr but correctly
reports the
problem as occuring on line 6.

I’m not sure there is any way to fix this without breaking other
things. You see, the substr() call creates a special magical scalar
and that scalar is passed to foo(). It is only when you try to read
from that scalar (or assign to it) that perl finds out that it
represents a substring outside of the target string.

It is necessary for it to work this way in the case of variables, as
in foo(substr($bar, 4, 6)), because the value of $bar may change
before the substring is taken.

If we make this work differently for constant targets and variable
targets, then we get the warning occurring in different places; it
would be less predictable. So it’s six of one or half a dozen of the
other.

I wouldn't expect it to work differently for variables and constants; I just happened to use a constant in my example. In the real code where I discovered the issue I was using a variable. (The constant case seems unlikely for real code.)

I don't know enough about the internals to know how to fix it, but presumably any attempt would require the magic scalar to include a reference to the warnings flags from the scope where the substr appears. That said, I can imagine wanting different behavior depending on whether the substr is used as an rvalue or an lvalue. For my example (rvalue) usage I'd expect the error and "no warnings" to apply in the scope where the substr call appeared. For lvalue usage it would probably make more sense to report/warn from the scope where the magic scalar is used. :(

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

No branches or pull requests

2 participants