Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: "uninitialized value in subroutine exit" warning from CGI.pm

by haukex (Archbishop)
on Nov 10, 2017 at 10:30 UTC ( [id://1203113]=note: print w/replies, xml ) Need Help??


in reply to "uninitialized value in subroutine exit" warning from CGI.pm

Interesting, the only Google result for "uninitialized value in subroutine exit" (with quotes) is currently this thread. Here's an SSCCE to reproduce:

#!perl -w use warnings; use strict; use CGI; print "$] $CGI::VERSION\n"; sub Foo::get_end_date { return undef } my $pa = bless {}, 'Foo'; print CGI->new->textfield(-name=>"end_date", -default=>substr($pa->get_end_date(),0,10)), "\n"; __END__ 5.026000 4.36 Use of uninitialized value in subroutine exit at .../CGI.pm line 472. <input type="text" name="end_date" />

And a minimal test case is

$ perl -wle 'sub x{@_} print x(substr undef,0)'

On Perl 5.6 thru 5.14, this dies with "Use of uninitialized value in substr at -e line 1. Modification of a read-only value attempted at -e line 1." (which also doesn't seem quite right to me), whereas on Perls 5.16 thru 5.26 it gives the warning "Use of uninitialized value in subroutine exit at -e line 1.". A bisect shows the behavior changed with commit a74fb2cdc8f2. <update> I'm not an expert on the internals so I don't know if that commit is a red herring, or if the change was an unintended side effect of that commit, there is another commit that explains the change better, or something else. See replies. </update> Perl v5.16 was also the release of the "substr lvalue revamp", so I suspect a lot of code related to substr was modified. The release notes also say:

Passing a substring of a read-only value or a typeglob to a function (potential lvalue context) no longer causes an immediate "Can't coerce" or "Modification of a read-only value" error. That error occurs only if the passed value is assigned to.

Like LanX I suspect the whole thing has to do with the fact that substr is magical and returns a special lvalue that can modify the original string, in combination with the elements of @_ being aliases to the original parameters (Update before posting: as also said here by dave_the_m, who has deep knowledge of the internals). <update> I don't know what's going on at subroutine exit that would trigger the warning, but this issue may even be worth mentioning on P5P. See replies. </update> A few more comments on your code:

  • You've already said that you changed your code to avoid this in the first place; my suggestion would be to add a method to your API next to get_end_date (or a parameter to that method) that returns the 10-character string you want to display (I assume YYYY-MM-DD or something similar), perhaps even using "proper" methods for date/time handling like the core Time::Piece, the powerful DateTime, or functions provided by the database.

  • Perhaps you want to consider avoiding calling functions in the arguments to CGI methods in general, there have even been some vulnerabilities related to that, although I don't want to spread any FUD here - substr will probably never return anything other than a single value, and your code may very well not use the affected pattern anywhere, I'm just pointing this out as something to keep in mind.

  • Personally, I like to code defensively and sometimes will intentionally write ''.substr(...) to force the return value to be turned into a regular string if I suspect a risk of strange things happening with the lvalue.

  • I suspect you have -w on your shebang line. Note that the Perl documentation includes a section "What's wrong with * w* and $^W" (emphasis mine):

    Although very useful, the big problem with using -w on the command line to enable warnings is that it is all or nothing. Take the typical scenario when you are writing a Perl program. Parts of the code you will write yourself, but it's very likely that you will make use of pre-written Perl modules. If you use the -w flag in this case, you end up enabling warnings in pieces of code that you haven't written. ...

    I recommend you just use warnings; in your code and remove the -w from the shebang line, there may be other places where using -w (or $^W) may trigger warnings in code you don't have control over.

Replies are listed 'Best First'.
Re^2: "uninitialized value in subroutine exit" warning from CGI.pm
by dave_the_m (Monsignor) on Nov 10, 2017 at 15:26 UTC
    I don't know what's going on at subroutine exit that would trigger the warning
    On subroutine return, any return values are copied. If you return a substr lvalue, this will trigger the uninit warning at this point. For example this warns:
    sub f { $_[0] } $a = f(substr(undef,0,1));
    This is behaviour I would expect, and I'm not seeing a bug.

    Dave.

      On subroutine return, any return values are copied. [emphasis mine]

      D'oh! Thank you for the enlightenment on a Friday afternoon ;-)

      Update: Yep:

      $ perl -wMstrict *a = \substr(undef,0); # alias via glob $b = $a; # copy $a = 'x'; # assignment __END__ Use of uninitialized value in scalar assignment at - line 2. Modification of a read-only value attempted at - line 3.

      And just like above, on Perls <5.16 that dies with "Modification of a read-only value attempted at - line 1." (instead of line 3). So I should probably call the commit I referenced a bugfix! :-)

      Additional updates: Expanded the code example from the original version and added (and edited) the last paragraph.

Re^2: "uninitialized value in subroutine exit" warning from CGI.pm
by LanX (Saint) on Nov 10, 2017 at 14:23 UTC
    on a side note, the warning doesn't appear inside the debugger

    C:\Windows\system32>perl -e "use warnings; sub x{@_} print x(substr un +def,0)" Use of uninitialized value in subroutine exit at -e line 1. C:\Windows\system32>perl -de0 Loading DB routines from perl5db.pl version 1.37 ... DB<1> use warnings; sub x{@_} print x(substr undef,0) DB<2> print $] 5.016003

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1203113]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (6)
As of 2024-04-23 18:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found