diff --git a/lib/File/stat.pm b/lib/File/stat.pm index a2a2b09b56b7..192df7bbdb42 100644 --- a/lib/File/stat.pm +++ b/lib/File/stat.pm @@ -1,4 +1,4 @@ -package File::stat 1.14; +package File::stat 1.15; use v5.38; use warnings::register; @@ -200,14 +200,16 @@ sub stat :prototype($) { my $arg = shift; my $st = populate(CORE::stat $arg); return $st if defined $st; - my $fh; + return if ref $arg; + # ... maybe $arg is the name of a bareword handle? + my $fh; { - local $!; - no strict 'refs'; - require Symbol; - $fh = \*{ Symbol::qualify( $arg, caller() )}; - return unless defined fileno $fh; - } + local $!; + no strict 'refs'; + require Symbol; + $fh = \*{ Symbol::qualify( $arg, caller() )}; + return unless defined fileno $fh; + } return populate(CORE::stat $fh); } diff --git a/lib/File/stat.t b/lib/File/stat.t index b5475f9d89f7..0175a9304b3f 100644 --- a/lib/File/stat.t +++ b/lib/File/stat.t @@ -191,6 +191,40 @@ SKIP: ok(-p($pstat), "check -p detects a pipe"); } +{ + # GH #23507 + { + package PathObj; + use overload + '""' => sub { $_[0]->to_string }, + fallback => 1; + + sub new { + my $class = shift; + bless { path => $_[0] }, $class + } + + sub to_string { + my $self = shift; + $self->{path} + } + } + + my $good_path = PathObj->new($file); + my $bad_path = PathObj->new('/ no such file'); + + # explicit stringification + isa_ok stat("$good_path"), 'File::stat', 'stat("$good_path")'; + is stat("$bad_path"), undef, 'stat("$bad_path") fails by returning undef'; + # implicit stringification + isa_ok stat($good_path), 'File::stat', 'stat($good_path)'; + is stat($bad_path), undef, 'stat($bad_path) fails by returning undef'; + # and for good measure, unblessed references + is stat(\42), undef, 'stat(\42) fails by returning undef'; + is stat([]), undef, 'stat([]) fails by returning undef'; + is stat({}), undef, 'stat({}) fails by returning undef'; +} + # Testing pretty much anything else is unportable. done_testing;