views:

146

answers:

3

I've seen dozens of PHP snippets that go like this:

function DB_Quote($string)
{
    if (get_magic_quotes_gpc() == true)
    {
        $string = stripslashes($string);
    }

    return mysql_real_escape_string($string);
}

What happens if I call DB_Quote("the (\) character is cool");? (Thanks jspcal!)

Aren't we supposed to strip slashes only when get_magic_quotes_gpc() == true and the value originated from $_GET, $_POST or $_COOKIE superglobals?

+2  A: 

yeah as dav said, up to the script to only use stripslashes on form input...

if you call stripslashes with the string "O'Reilly", the string won't be changed. if you call stripslashes with a string like: "the backslash (\) character is cool", the result will replace the escape sequence \) with ). so, using that function on all db values could subtly break things, but it might not be noticed.

like many apps, you could also just not support magic quotes mode. check for it and print an error if it's on. it's been off by default for years and it's not recommended.

jspcal
It does change it: `DB_Quote("O'Reilly") == O\'Reilly`.
nickf
stripslashes doesn't change it, but mysql_real_escape does
jspcal
ah sorry - i misread your answer.
nickf
+3  A: 

Yeah, I've seen dozens of PHP snippets like that, too. It's a bit sad.

Magic quotes are an input issue. It has to be fixed at the input stage, by iterating the GET/POST/COOKIES arrays and removing the slashes, if you need your app to run on servers using the foul archaic wrongness that is magic_quotes_gpc. The simple alternative is to detect the magic quotes option and die with a “your server sucks” error when set.

mysql_real_escape_string is an output issue. It needs to be run on the way out of the script, on content heading to the database, if you're not using parameterised queries (which you should definitely consider).

These are two separate unrelated stages in the program. You can't put them in the same function, tempting though it may be to try to encapsulate all your string processing into one box.

Aren't we supposed to strip slashes only when [...] the value originated from $_GET, $_POST or $_COOKIE superglobals?

Yes, exactly. Which is why the snippet you quoted is indeed harmful. Because tracking the origin of a string is impractical (especially as you might combine strings from different sources, one of which is slashed and the other not), you can't do it in one function. It has to be two separate string handling functions called at the appropriate time.

bobince
+6  A: 

Step one is to turn off magic quotes altogether and issue large unignorable warnings if it is on.

If this isn't an option to you, then in my opinion, the best way to go is to remove all magic quotes all the time.

// in a function called on every page load:
if (get_magic_quotes_gpc()) {
    foreach (array('_GET', '_POST', '_COOKIE', '_REQUEST') as $src) {
        foreach ($$src as $key => $val) {
            $$src[$key] = stripslashes($val);
        }
    }
}

A small performance hit, but will give you a LOT more ease of mind when working with your variables from then on.

nickf
agreed - better to turn off... or change to another host
HorusKol
+1, I use similar code in all of my projects too. Magic quotes are the most vicious malice of PHP known to date. The intent was good, but the realization is vicious and error-prone. Disable is good, and in software (written to be distributed on any PHP thing) **you just have to use this workaround** (the code of this answer, executed as early as possible).
frunsi
@nickf: What about `$_REQUEST`, should I also stripslash it or are the changes reflected automatically?
Alix Axel
I'm used to adding such kind of snippet to all my PHP projects now. Magic_quotes is a evil function and I'm glad they will remove it in PHP6 (Or us developers will get a nightmare)
Jimmie Lin