Perl Bug 1 - ~negating strings


#!/opt/perl5.004/bin/perl

# Around perl5.002 (I'm guessing perl5.0), they added the ability to
# ~negate strings.  Previous perl would int() a string first (usually
# resulting in negating 0).  In perl5.004 this somehow introduced a
# bug with normal integer negations.  If perl had string and integer
# versions of a variable it would choose which to use based on the
# history of the variable.  As far as I can tell it would use whatever
# value it was last used as, unless the MSB was high in the integer,
# or if int() had ever been called on it.  That's weird.
# Anyways, this was a problem because when you print an integer it
# stringizes it and saves the string version with the integer - then you
# end up using the string when you try to negate it.  In perl5.004_03
# they must have figured this out (it was in pre-release when I found this),
# because it seems that they now only negate the string version if they
# don't have an integer version.

$mask=0x80000000;       # Set mask with MSB=1
"$mask";                # Stringize mask (cached in the variables history)
print ~$mask, "\n";     # NEGATES INT

$mask=0x40000000;       # Now try with MSB=0
"$mask";
print ~$mask, "\n";     # NEGATES *STRING* VALUE        <-- BUG!!!

$mask=0x40000000;       # This works
print ~$mask, "\n";     # NEGATES INT

$mask=0x40000000;
"$mask";
$mask+1;                # We use it as an int again
print ~$mask, "\n";     # NEGATES INT

$mask=0x40000000;       # This is not
int($mask);             # This permanently clobbers mask as an int?
"$mask";
print ~$mask, "\n";     # NEGATES INT

##################################################
#
# Here's another manifestation of the bug
#

$a=-53;
printf "HEY: $a %d %x\n",$a,$a;
$a=$a & (~3);           # This should recognize $a as unsigned from here out
                        # But in perl5.002 it becomes some sort of string.
printf "HEY: $a %d %x\n",$a,$a;