tags:

views:

109

answers:

5

A problem I recently ran into was that when trying to update a field in my database using this code would not work. I traced it back to having a % sign in the text being updated ($note, then $note_escaped)... Inserting it with sprintf worked fine though.

Should I not be using sprintf for updates, or should it be formed differently?

I did some searching but couldn't come up with anything.

$id = mysql_real_escape_string($id);
$note_escaped = mysql_real_escape_string($note);
$editedby = mysql_real_escape_string($author);
$editdate = mysql_real_escape_string($date);
//insert info from form into database
$query= sprintf("UPDATE notes_$suffix SET note='$note_escaped', editedby='$editedby', editdate='$editdate' WHERE id='$id' LIMIT 1");

Thanks much!

+1  A: 

You can escape the % in the source text by replacing it with \% in mysql.

vfilby
The correct way to escape in mysql is \% - http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
Ivo Sabev
My, bad. Corrected.
vfilby
+5  A: 

You are using sprintf totally wrong. Removing the function call in your code would still do the same thing. It should be:

sprintf("UPDATE notes_%s SET note='%s', editedby='%s', editdate='%s' WHERE id=%d LIMIT 1", $suffix, $note_escaped, $editedby, $editdate, $id);

You should read the manual.

Coronatus
removing the function call? you mean mysql_real_escape_string? that's a stupid advice to give
knittl
@knittl - No, removing sprintf would give identical code. Where the hell did I even mention mysql_real_escape_string?
Coronatus
from your answer it sounds like it, you talk about removing a function call—what function call?—ah, you're talking about sprintf—and do not show the escape function calls in your code. it could be a bit misleading
knittl
Thanks. I do read the manual, by the way. It's not very clear on this.. I arrived at my code when trying to figure out how to convert my perfectly working INSERT sprintf code to UPDATE code, and I tried to get it to work and couldn't..
Cameron Conner
A: 

From http://php.net/manual/en/function.mysql-real-escape-string.php:

Note: mysql_real_escape_string() does not escape % and _. These are wildcards in MySQL if combined with LIKE, GRANT, or REVOKE.

You need to manually escape the % and _ if any with \% and _. I don't recommend using sprintf, but just improving your escape function.

Ivo Sabev
+1  A: 

sprintf() is not used much in PHP, unless you need to format data somehow. These two statements work identically in PHP:

$num = 42;
$char = 'q';

$text = sprintf('The number is %d and the character is %s', $num, $char);
$text = "The number is $num and the character is $char";

sprintf's used more in C for "printing" variable data into a string. But PHP can already do that with double-quoted strings, so unless you need to use sprintf's special formatting functions (e.g. %0.2f for a 2-decimal-place float), it's easier to use the regular string method.

Marc B
hell will freeze over if you create sql-strings with variable substitution in double quoted strings
knittl
Building queries manually is only dangerous if you're unaware of SQL injection, and/or don't care. Screaming that manual queries are dangerous from the rooftops doesn't help to educate beginners.
Marc B
It seems that I read something somewhere that sprintf() was a faster way to execute mysql queries than a normal variable string.
Cameron Conner
Nope. Double-quoted strings are actually much much faster. There's no format parsing overhead: http://judebert.com/progress/archives/204-PHP-String-Formatting-Performance.html
Marc B
Thanks for the info Marc.
Cameron Conner
+2  A: 

first of all you should be using prepared statements instead of a sprintf-call

but if you absolutely have to do it this way you have to use:

$id = mysql_real_escape_string($id);
$note_escaped = mysql_real_escape_string($note);
$editedby = mysql_real_escape_string($author);
$editdate = mysql_real_escape_string($date);
//insert info from form into database
$query= sprintf("
  UPDATE notes_%s /* this is still open for injection, and cannot be properly escaped with mysql_real_escape_string */
  SET note='%s', 
  editedby='%s', 
  editdate='%s' 
  WHERE id='%d'
  LIMIT 1",
$suffix,
$note_escaped, $editedby, $editdate, $id);
knittl