-5

Edit: I did try using eq instead of == earlier, and it did not work. For some reason now it does. It's possible that there was another error at that point which prevented it from working, but now this has been resolved. Thank you.

I'm trying to do some simple validation. I want to make sure the redirect url being fed through a variable begins with a particular site or not. If it does, the redirect goes through, if not, it redirects to the root of the site. Seems pretty straight forward, right?

$redir = $input{'redirect'};
$redir_sub = substr($redir, 0, 21);
if ($redir_sub == "http://www.mysite.com") {
     print "Location: $redir \n\n";
}else{
     print "Location: http://www.mysite.com \n\n";
}

The thing is, no matter what variable I place in there, it the "if" returns as true. I could put my favorite webcomic in there and it'll redirect to it, despite the string not matching. For example this:

$redir = $input{'redirect'};
$redir_sub = "http://www.yahoo.com"
if ($redir_sub == "http://www.mysite.com") {
     print "Location: $redir_sub \n\n";
}else{
     print "Location: http://www.mysite.com \n\n";
}

That redirects to yahoo! What is going on?

innaM
  • 47,505
  • 4
  • 67
  • 87
Marcel Marino
  • 962
  • 3
  • 17
  • 34

5 Answers5

2

Operator == is used to compare numbers. You should replace it with operator eq

Galimov Albert
  • 7,269
  • 1
  • 24
  • 50
2
if ($redir_sub == "http://www.mysite.com")

should be

if ($redir_sub eq "http://www.mysite.com")

as eq is string equality operator, and using == forces number comparison so in this case condition always evaluates to trues as 0 == 0 is true.

mpapec
  • 50,217
  • 8
  • 67
  • 127
  • Huh. Weird. I tried eq earlier and it didn't work. Now it does. Thanks. – Marcel Marino Jun 10 '13 at 17:30
  • 1
    just before if condition you can `print qq($redir_sub eq "http://www.mysite.com");` to check what is being evaluated. – mpapec Jun 10 '13 at 17:33
  • 3
    @MarcelMarino No, you didn't. You *think* you tried it earlier. `use warnings` and you will find that your "bugs" become much less mysterious. – TLP Jun 10 '13 at 17:42
2

TL;DR: use eq not ==!


Perl as a language seems to have a problem: It uses the same data type (the scalar) for a lot of different things, including strings and numbers. A scalar is both at the same time, not just one of those. Perl has no type annotations, and there is no way to indicate if a variable holds a string or a number.

This produces problems when we consider equality tests. Assuming two scalars $a = "42.0" and $b = 42. Are they equal? Yes and no:

  • The strings "42" and "42.0" are not the same thing! These are not equal.
  • The numbers 42 and 42.0 are equal!

As indicated above, Perl does not use a type system to solve this ambiguity. Rather, it uses different sets of operators for string and numeric operations:

eq ne lt le gt ge cmp
== != <  <= >  >= <=> 
amon
  • 57,091
  • 2
  • 89
  • 149
  • also ~~ smart match operator can be used for string and num comparsion both. and `42 ~~ "42";42 ~~ "42.0";42 ~~ "42\n";42 ~~ "42 "` will be true – Suic Jun 10 '13 at 17:34
  • @Suic Using smartmatch for this is a rather bad idea, as `"42" ~~ "42.0"` won't evaluate to true. For this kind of comparision, it is always better to explicitely use string or numeric comparision. The other option is to explicitely numify/stringify the smartmatch args: `0+$a ~~ 0+$b` or `"$a" ~~ "$b"`. Also, smartmatch behaviour is likely to change in upcoming releases of perl. – amon Jun 10 '13 at 17:41
2

Your problem is that you are not using

use warnings;

Which is why Perl is allowing you to make this mistake. You are using the numeric equality operator to compare strings. Hence, Perl first tries to convert each parameter to a number. And since your strings do not begin with numbers (and do not look like numbers), they are converted to zero 0. Hence your expression

if ($redir_sub == "http://www.mysite.com")

Really means this

if (0 == 0)

Which of course always returns true.

If you had been using warnings, you would have gotten the errors:

Argument "http..." isn't numeric in numeric eq (==) at ...
Argument "http..." isn't numeric in numeric eq (==) at ...

Which would have been a hint as to your problem that you should be using eq and not == to compare strings.

TLP
  • 66,756
  • 10
  • 92
  • 149
1

== does numeric comparison. eq does string comparison. When you use a string as a number, perl passes your string through your c library's aton(). So you're really asking your computer if 0 == 0 which is true.

tjd
  • 4,064
  • 1
  • 24
  • 34