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

*FILE{IO} does not behave like *FILE for stat() and -X() operators #4837

Closed
p5pRT opened this issue Jan 15, 2002 · 9 comments
Closed

*FILE{IO} does not behave like *FILE for stat() and -X() operators #4837

p5pRT opened this issue Jan 15, 2002 · 9 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 15, 2002

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

Searchable as RT8244$

@p5pRT
Copy link
Author

p5pRT commented Jan 15, 2002

From @jlokier

Created by @jlokier

I use the following code to generate file handles, as per the perlref manpage​:

  local *FILE;
  open FILE, "<blahblah" or die "Error opening \`blahblah'​: $!\n";
  return *FILE{IO};

For the most part, this has the same effect as returning *FILE, and
seems cleaner. The perlref manpage seems to recommend this, although
the perlfaq5 page seems to prefer the *FILE approach.

Although this works fine with functions like `read', `write', `sysread'
etc., it generates an unexpected result with `stat', `lstat' and the
`-X' file test operators.

Specifically, when one of these *FILE{IO} references is used in the file
test functions, including `stat' and `lstat', it's converted to a string
(i.e. "IO​::Handle=IO(0x12345678)"), and that is used as the file name to
test.

On the other hand, when a typeglob *FILE is used in a file test
function, the fstat() system call is used on the open file as expected.

Is this a code discrepancy or something that should be documented in the
perlfunc manpage?

Cheers,
-- Jamie Lokier

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl v5.6.0:

Configured by bhcompile at Thu Aug  9 22:47:55 EDT 2001.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.6-3.1enterprise, archname=i386-linux
    uname='linux stripples.devel.redhat.com 2.4.6-3.1enterprise #1 smp tue jul 24 14:03:17 edt 2001 i686 unknown '
    config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc -Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=undef d_sfio=undef uselargefiles=undef 
    use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef
  Compiler:
    cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 20000731 (Red Hat Linux 7.1 2.96-96)
    cppflags='-fno-strict-aliasing -I/usr/local/include'
    ccflags ='-fno-strict-aliasing -I/usr/local/include'
    stdchar='char', d_stdstdio=define, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4
    alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lcrypt
    libc=/lib/libc-2.2.4.so, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.6.0:
    /usr/lib/perl5/5.6.0/i386-linux
    /usr/lib/perl5/5.6.0
    /usr/lib/perl5/site_perl/5.6.0/i386-linux
    /usr/lib/perl5/site_perl/5.6.0
    /usr/lib/perl5/site_perl
    .


Environment for perl v5.6.0:
    HOME=/home/jamie
    LANG=en_GB
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/jamie/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/home/jamie/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


@p5pRT
Copy link
Author

p5pRT commented Jul 28, 2006

From @smpeters

On Tue Jan 15 00​:10​:56 2002, jamie wrote​:

This is a bug report for perl from jamie@​shareable.org,
generated with the help of perlbug 1.28 running under perl v5.6.0.

-----------------------------------------------------------------
[Please enter your report here]

I use the following code to generate file handles, as per the perlref
manpage​:

local *FILE;
open FILE, "<blahblah" or die "Error opening \`blahblah'​: $!\n";
return *FILE{IO};

For the most part, this has the same effect as returning *FILE, and
seems cleaner. The perlref manpage seems to recommend this, although
the perlfaq5 page seems to prefer the *FILE approach.

Although this works fine with functions like `read', `write',
`sysread'
etc., it generates an unexpected result with `stat', `lstat' and the
`-X' file test operators.

Specifically, when one of these *FILE{IO} references is used in the
file
test functions, including `stat' and `lstat', it's converted to a
string
(i.e. "IO​::Handle=IO(0x12345678)"), and that is used as the file name
to
test.

On the other hand, when a typeglob *FILE is used in a file test
function, the fstat() system call is used on the open file as
expected.

Is this a code discrepancy or something that should be documented in
the
perlfunc manpage?

Cheers,
-- Jamie Lokier

Sorry about not responding to this earlier. This problem has been fixed
with change #28628.

@p5pRT
Copy link
Author

p5pRT commented Jul 28, 2006

@smpeters - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Jul 28, 2006
@p5pRT
Copy link
Author

p5pRT commented Aug 9, 2006

From @doughera88

On Thu, 27 Jul 2006, Steve Peters via RT wrote​:

On Tue Jan 15 00​:10​:56 2002, jamie wrote​:

This is a bug report for perl from jamie@​shareable.org,
generated with the help of perlbug 1.28 running under perl v5.6.0.

Although this works fine with functions like `read', `write',
`sysread'
etc., it generates an unexpected result with `stat', `lstat' and the
`-X' file test operators.

Specifically, when one of these *FILE{IO} references is used in the
file
test functions, including `stat' and `lstat', it's converted to a
string
(i.e. "IO​::Handle=IO(0x12345678)"), and that is used as the file name
to
test.

On the other hand, when a typeglob *FILE is used in a file test
function, the fstat() system call is used on the open file as
expected.

Sorry about not responding to this earlier. This problem has been fixed
with change #28628.

Thanks (and sorry to bother the original poster with yet another
follow-up) but there's a subtle problem (actually discovered by Coverity).
Specifically, in this bit of code (starting around line 2839)
 
  SV* const sv = POPs;
  if (SvTYPE(sv) == SVt_PVGV) {
  gv = (GV*)sv;
  goto do_fstat;
  } else if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
  gv = (GV*)SvRV(sv);
  if (PL_op->op_type == OP_LSTAT)
  goto do_fstat_warning_check;
  goto do_fstat;
  } else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) {
  io = (IO*)SvRV(sv);
  if (PL_op->op_type == OP_LSTAT)
  goto do_fstat_warning_check;
  goto do_fstat_have_io;
  }

the last clause can end up doing a 'goto do_fstat_warning_check' without
ever setting gv. That warning check can indeed try to dereference gv.

The following test script (stripped down from t/op/stat.t) illustrates the
problem. It currently core dumps at the XXX line while trying to warn
"lstat() on filehandle %s", GvENAME(gv), and dumps core since gv is NULL.
I haven't dug deeply enough to decide whether to just beef up the warning
message (and the corresponding perldiag entry) or whether there's some way
to make some more useful information available.

  #!./perl
  BEGIN {
  chdir 't' if -d 't';
  @​INC = '../lib';
  require './test.pl'; # for which_perl() etc
  }
  use warnings;
  plan tests => 5;
  my $tmpfile = "Op_stat.tmp";
  1 while unlink $tmpfile;

  ok(open(F, ">", $tmpfile), 'can create temp file');
  my @​thwap = stat *F{IO};
  ok(@​thwap, "stat(*F{IO}) works");
  ok( -f *F{IO} , "single file tests work with *F{IO}");
  unlink $tmpfile;
 
  ok(open(F, ">", $tmpfile), 'can create second temp file');
  my @​thwap2 = lstat *F{IO}; # XXX Note incorrectly using an lstat().
  # Not sure just what to test for here. These tests are probably
  # not right.
  ok(@​thwap2, "lstat(*F{IO}) works"); # Probably not right

  END {
  1 while unlink $tmpfile;
  }

--
  Andy Dougherty doughera@​lafayette.edu

@p5pRT
Copy link
Author

p5pRT commented Aug 10, 2006

From @rgs

Andrew Dougherty wrote​:

The following test script (stripped down from t/op/stat.t) illustrates the
problem. It currently core dumps at the XXX line while trying to warn
"lstat() on filehandle %s", GvENAME(gv), and dumps core since gv is NULL.
I haven't dug deeply enough to decide whether to just beef up the warning
message (and the corresponding perldiag entry) or whether there's some way
to make some more useful information available.

Not seeing an obvious way to get more useful information, I've for now
plugged the hole by change #28690​:

- "lstat() on filehandle %s", GvENAME(gv));
+ "lstat() on filehandle %s", gv ? GvENAME(gv) : "");

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2012

From @cpansprout

On Thu Jul 27 17​:43​:43 2006, stmpeters wrote​:

On Tue Jan 15 00​:10​:56 2002, jamie wrote​:

This is a bug report for perl from jamie@​shareable.org,
generated with the help of perlbug 1.28 running under perl v5.6.0.

-----------------------------------------------------------------
[Please enter your report here]

I use the following code to generate file handles, as per the perlref
manpage​:

local *FILE;
open FILE, "<blahblah" or die "Error opening \`blahblah'​: $!\n";
return *FILE{IO};

For the most part, this has the same effect as returning *FILE, and
seems cleaner. The perlref manpage seems to recommend this, although
the perlfaq5 page seems to prefer the *FILE approach.

Although this works fine with functions like `read', `write',
`sysread'
etc., it generates an unexpected result with `stat', `lstat' and the
`-X' file test operators.

Specifically, when one of these *FILE{IO} references is used in the
file
test functions, including `stat' and `lstat', it's converted to a
string
(i.e. "IO​::Handle=IO(0x12345678)"), and that is used as the file name
to
test.

On the other hand, when a typeglob *FILE is used in a file test
function, the fstat() system call is used on the open file as
expected.

Is this a code discrepancy or something that should be documented in
the
perlfunc manpage?

Cheers,
-- Jamie Lokier

Sorry about not responding to this earlier. This problem has been fixed
with change #28628.

Except that change missed -t, -T and -B. So I’m reopening it.

Is this something we can fix for 5.16? Is it possible that someone is
relying on -T *$fh{IO} treating the ref as a file name?

Also, that commits causes lstat(*$fh{IO}) to do the same thing as
stat(_), but with a warning. Shouldn’t it revert to stat(*$fh{IO}, just
as lstat(HANDLE) reverts to stat(HANDLE) (but with a warning)?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2012

@cpansprout - Status changed from 'resolved' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2012

From @cpansprout

On Thu Aug 10 02​:48​:16 2006, rgarciasuarez@​mandriva.com wrote​:

Andrew Dougherty wrote​:

The following test script (stripped down from t/op/stat.t)
illustrates the
problem. It currently core dumps at the XXX line while trying to
warn
"lstat() on filehandle %s", GvENAME(gv), and dumps core since gv is
NULL.
I haven't dug deeply enough to decide whether to just beef up the
warning
message (and the corresponding perldiag entry) or whether there's
some way
to make some more useful information available.

Not seeing an obvious way to get more useful information, I've for now
plugged the hole by change #28690​:

- "lstat() on filehandle %s", GvENAME(gv));
+ "lstat() on filehandle %s", gv ? GvENAME(gv) :
"");

That leaves a double space before ‘at’​:

lstat() on filehandle at -e line 1.

I’ve just fixed that in commit 93fad93.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2012

From @cpansprout

On Fri Jan 13 22​:38​:26 2012, sprout wrote​:

Also, that commits causes lstat(*$fh{IO}) to do the same thing as
stat(_), but with a warning. Shouldn’t it revert to stat(*$fh{IO}, just
as lstat(HANDLE) reverts to stat(HANDLE) (but with a warning)?

It’s actually documented to do an fstat in perldiag. So I’ve changed it
to do that, with commit 0d5064f.

-t, -T and -B still do not accept iorefs. I haven’t changed that (yet).

--

Father Chrysostomos

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

1 participant