Hidden string formatting bug

Steve Holden steve at holdenweb.com
Fri Oct 14 01:01:15 EDT 2005


Tim Peters wrote:
> [Echo]
> 
>>I have been trying to figure out the problem with this string formatting:
> 
> 
> [monstrous statement snipped]
> 
> 
>>when it executes, I get this error: "inv argument required".
> 
> 
> That shoud be "int", not "inv".
> 
> 
>>I have checked and rechecked both the string and the tuple. I cant figure
>>out what the problem is.  After playing around with it, i found out if change
>>the last line to: "%s,%i) %(... I get a different error. The error is "not all
>>arguments converted during string formatting".
>>
>>So I am baffled and confused as of why this wont work. Is anyone able to
>>shed some light on my hidden bug?
> 
> 
> Yup, it's precedence.  Here's the same thing:
> 
> sql = "%s" + \
>       "%i" % ("abc", 2)
> 
> Run that and you get "int argument required".  Change the last %i to
> %s and you get "not all arguments converted during string formatting".
>  Both error messages are accurate.
> 
> That's because % binds tighter than "+".  As a 1-liner, and inserting
> redundant parentheses to make the precedence obvious, my simplified
> example is
> 
> sql = "%s" + ("%i" % ("abc", 2))
> 
> What you intended _requires_ inserting more parentheses to force the
> intended order (if you're going to stick to this confusing coding
> style):
> 
> sql = ("%s" + "%i") % ("abc", 2)
> 
> Better is to not use "+" on string literals, and not use backslash
> continuation either; try this instead:
> 
> sql_format = ('string1'
>                     'string2'
>                     'string3'
>                     ...
>                     'last string')
> 
> Build the format in a separate statement to reduce the chance of
> errors (for example, your original mistake would have been impossible
> to make this way).  Use parens instead of backslashes.  Don't use "+"
> to catenate string literals:  the Python compiler automatically
> catenates adjacent string literals for you, and at compile-time (so
> it's even more efficient than using '"+").

Further to Tim's erudite language advice, I should point out the 
oft-repeated advice that you are leaving yourself wide open to SQL 
injection exploits here, and you should definitely consider using 
parameterised queries, which have been discussed here so often (and too 
recently for me to repeat) that you should easily be able to find them 
with Google.

regards
  Steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC                     www.holdenweb.com
PyCon TX 2006                  www.python.org/pycon/




More information about the Python-list mailing list