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
Constant strings representing a number can BECOME numbers #6266
Comments
From perl-5.8.0@ton.iguana.beCreated by perl-5.8.0@ton.iguana.beperl -wle 'sub fun { print+(shift() & "+0") eq "0" ? "yes" : "no"} fun("waf"); fun(0); fun("waf")' This was code attempting to determine if a passed argument was "really" However, it seems that once "+0" has interacted in the & with a number, it While this is "normal" behaviour for variables, I don't think that Perl Info
|
From @hvds"perl-5.8.0@ton.iguana.be (via RT)" <perlbug-followup@perl.org> wrote: Hmm, tricky I think. In most cases, caching conversion results for In this case, the easiest way to avoid it is not to be a constant: What else is broken by upgrading constants in this way? Hugo |
From perl5-porters@ton.iguana.beIn article <200302120433.h1C4XdX03020@crypt.compulink.co.uk>,
Is it really ? How often would somebody write e.g. $x += "1" ?
It probably only matters in the cases where the behaviour of string Mmm, can the constant conversion actually be done at compile time, |
From @cpansproutI believed the attached patch is self-explanatory. |
From @cpansproutInline Patchdiff -Nup blead/pp.c blead-20661-str-becomenig-num/pp.c
--- blead/pp.c 2010-07-28 03:15:10.000000000 -0700
+++ blead-20661-str-becomenig-num/pp.c 2010-08-01 14:18:56.000000000 -0700
@@ -2387,6 +2387,10 @@ PP(pp_bit_and)
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
+ const bool left_must_not_turn_into_a_number
+ = cBINOP->op_first->op_type == OP_CONST && !SvNIOKp(left);
+ const bool right_must_not_turn_into_a_number
+ = cBINOP->op_last->op_type == OP_CONST && !SvNIOKp(right);
if (PL_op->op_private & HINT_INTEGER) {
const IV i = SvIV_nomg(left) & SvIV_nomg(right);
SETi(i);
@@ -2395,6 +2399,8 @@ PP(pp_bit_and)
const UV u = SvUV_nomg(left) & SvUV_nomg(right);
SETu(u);
}
+ if (left_must_not_turn_into_a_number) SvNIOK_off(left);
+ if (right_must_not_turn_into_a_number) SvNIOK_off(right);
}
else {
do_vop(PL_op->op_type, TARG, left, right);
@@ -2413,6 +2419,10 @@ PP(pp_bit_or)
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
+ const bool left_must_not_turn_into_a_number
+ = cBINOP->op_first->op_type == OP_CONST && !SvNIOKp(left);
+ const bool right_must_not_turn_into_a_number
+ = cBINOP->op_last->op_type == OP_CONST && !SvNIOKp(right);
if (PL_op->op_private & HINT_INTEGER) {
const IV l = (USE_LEFT(left) ? SvIV_nomg(left) : 0);
const IV r = SvIV_nomg(right);
@@ -2425,6 +2435,8 @@ PP(pp_bit_or)
const UV result = op_type == OP_BIT_OR ? (l | r) : (l ^ r);
SETu(result);
}
+ if (left_must_not_turn_into_a_number) SvNIOK_off(left);
+ if (right_must_not_turn_into_a_number) SvNIOK_off(right);
}
else {
do_vop(op_type, TARG, left, right);
diff -Nurp blead/t/op/bop.t blead-20661-str-becomenig-num/t/op/bop.t
--- blead/t/op/bop.t 2009-11-19 08:51:40.000000000 -0800
+++ blead-20661-str-becomenig-num/t/op/bop.t 2010-08-01 14:06:50.000000000 -0700
@@ -15,7 +15,7 @@ BEGIN {
# If you find tests are failing, please try adding names to tests to track
# down where the failure is, and supply your new names as a patch.
# (Just-in-time test naming)
-plan tests => 161 + (10*13*2) + 4;
+plan tests => 170 + (10*13*2) + 4;
# numerics
ok ((0xdead & 0xbeef) == 0x9ead);
@@ -63,6 +63,20 @@ is (($foo | $bar), ($Aoz x 75 . $zap));
# ^ does not truncate
is (($foo ^ $bar), ($Axz x 75 . $zap));
+# string constants
+sub _and($) { $_[0] & "+0" }
+sub _oar($) { $_[0] | "+0" }
+sub _xor($) { $_[0] ^ "+0" }
+is _and "waf", '# ', 'str var & const str'; # These three
+is _and 0, '0', 'num var & const str'; # are from
+is _and "waf", '# ', 'str var & const str again'; # [perl #20661]
+is _oar "yit", '{yt', 'str var | const str';
+is _oar 0, '0', 'num var | const str';
+is _oar "yit", '{yt', 'str var | const str again';
+is _xor "yit", 'RYt', 'str var ^ const str';
+is _xor 0, '0', 'num var ^ const str';
+is _xor "yit", 'RYt', 'str var ^ const str again';
+
#
is ("ok \xFF\xFF\n" & "ok 19\n", "ok 19\n");
is ("ok 20\n" | "ok \0\0\n", "ok 20\n"); |
From @cpansproutOn Aug 1, 2010, at 2:22 PM, Father Chrysostomos wrote:
Someone pointed out to me that it would likely be reviewed more quickly if I provided a commit message, so here it is: This patch solves the problem of $x & "+0" not treating the RHS as a string if, on a previous invocation, the LHS happened to be a number (similarly with the other bitwise ops, too). This patch takes the conservative approach of fixing *just* those cases that have explicit quotation marks in the source code, which are clearly broken (and also ‘use constant’-style string constants, which are indistinguishable). (Read-only variables are slightly controversial still, and my patch does not affect those.) It does this by making the appropriate pp_ funcitons look at the op tree to see whether either operand is a constant during a numeric bitwise operation. If it is, and it is not numeric, it turns off the numericness (numericality?) before returning. |
From @cpansproutOn Wed Feb 12 14:13:32 2003, perl5-porters@ton.iguana.be wrote:
Commit b20c4ee stops bitops from coercing read-only arguments. |
@cpansprout - Status changed from 'open' to 'resolved' |
Migrated from rt.perl.org#20661 (status was 'resolved')
Searchable as RT20661$
The text was updated successfully, but these errors were encountered: