oxone has asked for the wisdom of the Perl Monks concerning the following question:

I came across some unexpected behaviour and I'd be very grateful for any insight as to why this happens. The odd behaviour is illustrated by the following minimal case:
use strict; use warnings; my $tainted = shift; my $test; $test = undef; $test += $tainted; print "Test 1: $test\n"; $test = undef; $test += $tainted; print "Test 2: $test\n";
This must be run with taint checking on in order to see the issue, so for this example, save as test.pl and run as follows with a numeric argument passed in, eg:
perl -T test.pl 1
Now, as I understand it, a '+=' op is allowed on an undefined value, so I'd expect this to work fine and to leave $test with a value of 1 in each case. However, the surprising thing is, this triggers a warning because $test is undefined, but ONLY the second time round after it has first been set with a tainted value and then undefined. So here's what happens:
%perl -T test.pl 1 Test 1: 1 Use of uninitialized value in addition (+) at test.pl line 12. Test 2: 1
I tested this on 2 different Perls, both with same result: It's easy to workaround (eg. don't undef the variable, or if it needs resetting, set it to zero) but I am curious as to why this happens? Anybody got a good explanation for this?

Replies are listed 'Best First'.
Re: Inconsistent warnings over undefined values
by ysth (Canon) on Jan 19, 2009 at 10:46 UTC
    The exemption of += from warning about an undef left operand is lost when the left operand has magic (specifically, get magic). This almost makes sense to me as a desirable behavior, but may just be an artifact of how the exemption is implemented (see below). Unfortunately tainting is managed with magic. The effect in this case could be construed as a bug.

    The exemption, where it applies, it checks for undef before trying to get the numeric value, but in the presence of magic, the flags used to check for undef are unreliable before the magic get, and the magic get is coupled to getting the numeric value which is coupled to producing the undef warning. In 5.8.9 and above, versions of the routines to get integer values are available that don't process magic (Sv[UI]V_nomg), but not the routine to get a floating point value (SvNV) or the routine to get an integer value only to see if the number is in range (SvIV_please). If those were available, the procedure could be changed to: get magic, check if undef, if so, assume 0 without warning, otherwise get the numeric value without magic.

      Thanks ysth, from a 'user' point of view I'd consider it a bug (it certainly looks and smells like one), but it's good to know there's an explanation for this within the internals.
A reply falls below the community's threshold of quality. You may see it by logging in.