Closed mauke closed 1 month ago
Could you provide some TODO-ed unit tests that will currently fail but will pass if this problem is corrected? Thanks.
pp_aelem and pp_alemfast return &PL_sv_undef for non-lvalue array lookups, so the check PerlIO_openn() does for undef
succeeds.
For the CORE::open() call:
open my $fh, '+>', (my $x = undef)
I'm not fond of this kind of magical "only-this-SV"-ness, though making it work for any undefined SV might cause other problems (eg. code that expects the open to fail for generic undef values).
I don't see a simple fix.
I have a couple of (ignorance-based¹) possible solutions:
&CORE::open
gets it right, so make open
also put its third argument in lvalue(-ish) context.open
introspect its op tree at runtime to see whether the &PL_sv_undef
came from a literal undef
arg.open(..., ..., undef)
and emit a different op (pp_open_tmpfile
?). Remove the special handling from regular open
.open
; don't define a separate op. In open
, only recognize &PL_sv_undef
as a temp file marker if that flag is set.¹ meaning I don't know how to actually implement them, which always makes it easier to say "just do X!"
While CORE::open() doesn't display this misbehaviour for the subscripting ops, it does display it for other OPs that return &PL_sv_undef
:
$ perl -we 'my $x; CORE::open(my $fh, "+>", delete $x{unknown}) or die $!'
Name "main::x" used only once: possible typo at -e line 1.
I considered some of these options.
Realize that both the normal open() op and CORE::open() end up being handled by pp_open, and the OP_OPEN generated by coresub_op() has generally default flags, so it wouldn't have a OPpSEEN_SV_UNDEF
private flag. This applies to the alternate OP too.
We could invert that flag, so OPpNO_SV_UNDEF_SEEN
and only do the temp file handling when that flag is missing, but it won't fix the delete
case above.
Also the undef
handling is actually done by PerlIO, so if pp_open decides not to do the temp file handling it will need to replace the &PL_sv_undef
with a sv_newmortal() (or non-mortal once pp_open is converted to PERL_RC_STACK).
So not simple, and doesn't fully fix it anyway.
Description
perldoc -f open
:This feature was added in 5.8.0 and is intended to only trigger when a literal
undef
is passed as the filename. It does not happen if a variable whose contents areundef
is used:Steps to Reproduce However, if you use an array or hash element that doesn't exist at all (as opposed to existing but containing
undef
), the special behavior kicks in andopen
silently succeeds, creating a temp file:Even this behavior is not entirely consistent, however. If you use a runtime call to
&CORE::open
, it starts failing again (but with duplicate warning messages for some reason):Expected behavior A call to
open
that does not pass a literalundef
, but an element of an array or hash, should complain about the undefined value and fail. Basically like the&CORE::open
version, but there I'd expect to see only one copy of the warning.Perl configuration