-
Notifications
You must be signed in to change notification settings - Fork 583
open unexpectedly creates temporary files with undefined variables sometimes #22385
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
Comments
Could you provide some TODO-ed unit tests that will currently fail but will pass if this problem is corrected? Thanks. |
Like this? blead...mauke:perl5:open-undef-todo-tests |
pp_aelem and pp_alemfast return &PL_sv_undef for non-lvalue array lookups, so the check PerlIO_openn() does for For the CORE::open() call:
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:
¹ 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
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 We could invert that flag, so Also the So not simple, and doesn't fully fix it anyway. |
Passing undef as the filename to open should create a temporary file. Previously, this was implemented as a simple `if (arg == &PL_sv_undef)` check. However, other operations (such as accessing non-existent array/hash elements) also return `&PL_sv_undef` directly, which `open` would then silently interpret as directions to create a temp file. Solution: Check (at compile time) whether the filename argument is an `OP_UNDEF`, and if so, set the `OPf_SPECIAL` flag on `OP_OPEN`. At runtime, if `&PL_sv_undef` is passed but `OPf_SPECIAL` is not set, replace it by a new mortal SV, which is treated as a regular filename (that happens to be undef) by PerlIO. (For runtime calls via `&CORE::open`, we cannot distinguish between `undef` and `delete $hash{nosuchkey}` as arguments, so to keep the `undef` case working, we always set `OPf_SPECIAL` in the generated core sub for `open`.) This functionality probably should be a private op flag (something like `OPpUNDEF_MEANS_TEMPFILE`?), but as far as I can tell, all possible private bits are already taken in `OP_OPEN`. Fixes Perl#22385.
Passing undef as the filename to open should create a temporary file. Previously, this was implemented as a simple `if (arg == &PL_sv_undef)` check. However, other operations (such as accessing non-existent array/hash elements) also return `&PL_sv_undef` directly, which `open` would then silently interpret as directions to create a temp file. Solution: Check (at compile time) whether the filename argument is an `OP_UNDEF`, and if so, set the `OPf_SPECIAL` flag on `OP_OPEN`. At runtime, if `&PL_sv_undef` is passed but `OPf_SPECIAL` is not set, replace it by a new mortal SV, which is treated as a regular filename (that happens to be undef) by PerlIO. (For runtime calls via `&CORE::open`, we cannot distinguish between `undef` and `delete $hash{nosuchkey}` as arguments, so to keep the `undef` case working, we always set `OPf_SPECIAL` in the generated core sub for `open`.) This functionality probably should be a private op flag (something like `OPpUNDEF_MEANS_TEMPFILE`?), but as far as I can tell, all possible private bits are already taken in `OP_OPEN`. Fixes Perl#22385.
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
The text was updated successfully, but these errors were encountered: