develooper Front page | perl.perl5.porters | Postings from August 2006

Re: [perl #8244] *FILE{IO} does not behave like *FILE for stat()and -X() operators

Thread Previous | Thread Next
Andrew Dougherty
August 9, 2006 12:15
Re: [perl #8244] *FILE{IO} does not behave like *FILE for stat()and -X() operators
Message ID:
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,
> > 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.

    BEGIN {
	chdir 't' if -d 't';
	@INC = '../lib';
	require './';	# 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

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About