2010-07-24 3 views
7

Il y a beaucoup de fonctions d'échappement dans le module mysqldb de Python dont je ne comprends pas la documentation, et mes efforts pour les rechercher n'ont rien révélé.Documentation mysqldb obscure de Python

>>> print _mysql.escape.__doc__ 
escape(obj, dict) -- escape any special characters in object obj 
using mapping dict to provide quoting functions for each type. 
Returns a SQL literal string. 

This documentation page dit la même chose. Mais qu'est-ce qui est supposé être dans ce "dict dicté"? J'ai essayé quelques trucs (la plupart du temps au hasard) et je n'ai que des erreurs. Ce qui est encore plus frustrant est que, alors que la méthode fonctionne escape_string(), sa chaîne de documentation est:

>>> print _mysql.escape_string.__doc__ 
escape_string(s) -- quote any SQL-interpreted characters in string s. 

Use connection.escape_string(s), if you use it at all. 
_mysql.escape_string(s) cannot handle character sets. You are 
probably better off using connection.escape(o) instead, since 
it will escape entire sequences as well as strings. 

Alors, je suis mieux à l'aide _mysql.escape(), suis-je? Eh bien, d'accord, mais comment? Que diable est ce "dict dicté"? PHP, de cette façon au moins, était beaucoup moins cryptique.

Répondre

7

J'ai appris cela en regardant dans /usr/lib/pymodules/python2.6/MySQLdb/connections.py pour voir comment ça s'appelle connection.escape. Un peu de reniflement conduit à MySQLdb.converters.conversions. Voici un extrait:

{0: <class 'decimal.Decimal'>, 
1: <type 'int'>, 
... 
<type 'dict'>: <built-in function escape_dict>, 
<type 'NoneType'>: <function None2NULL at 0xae9717c>, 
<type 'set'>: <function Set2Str at 0xae9709c>, 
<type 'str'>: <function Thing2Literal at 0xae971b4>, 
<type 'tuple'>: <built-in function escape_sequence>, 
<type 'object'>: <function Instance2Str at 0xae971ec>, 
<type 'unicode'>: <function Unicode2Str at 0xae9710c>, 
<type 'array.array'>: <function array2Str at 0xae9725c>, 
<type 'bool'>: <function Bool2Str at 0xae97294>} 

Vous pouvez l'utiliser comme ceci:

import MySQLdb 
import MySQLdb.converters 
import datetime 

now=datetime.datetime.now() 
connection=MySQLdb.connect(
    host=HOST,user=USER,passwd=PASS,db=MYDB) 
print(connection.escape((1,2,now),MySQLdb.converters.conversions)) 
# ('1', '2', "'2010-07-24 19:33:59'") 

PS. Concernant les tables Bobby: Pour une utilisation normale de MySQLdb, vous n'avez pas besoin d'échapper manuellement les arguments. Il suffit d'utiliser des arguments paramétrés lors de l'appel cursor.execute, et MySQLdb va automatiquement citer les arguments pour vous.

Par exemple:

sql='insert into students (name,grade,date) values (%s, %s, %s)' 
args=("Robert'); DROP TABLE Students; --",60,now) # no manual quotation necessary 
cursor=connection.cursor() 
cursor.execute(sql,args) 
+0

J'ai essayé votre évasion avec le nom de Little Bobby Tables, et cela a fonctionné. Mais, savoir que 'cursor.execute()' échappe automatiquement est également rassurant. Est-ce dans cette page de documentation liée à David Zaslavsky? Je ne l'ai pas vu là-bas ... Mais j'ai peut-être manqué ça. – eje211

+0

Si vous lisez la bande XKCD, le nom actuel de Bobby Tables est: "Robert"); DROP TABLE Students; - ". C'est un nom effrayant à mettre dans une base de données. Mais un bon cas de test. – eje211

+0

@ eje211: Votre question concernant l'endroit où la documentation explique la citation automatique des paramètres est une bonne question. Le meilleur que j'ai pu trouver est: 'Le client ne devrait pas être obligé de" s'échapper "de la valeur pour pouvoir l'utiliser', voir http://www.python.org/dev/peps/pep-0249/. – unutbu

2

En fait, il vaut mieux utiliser l'interface de plus haut niveau, MySQLdb. (Voir le user's guide)

Les fonctions _mysql sont vraiment juste des wrappers autour de l'API C. Ils sont censés être un détail d'implémentation, le genre de chose qui n'apparaîtrait même pas dans la documentation en PHP. Les développeurs les laissent peu documentés volontairement pour décourager les gens de les utiliser inutilement, et aussi parce que vous pouvez vous référer à MySQL C API documentation pour la fonction équivalente, ce qui est plutôt plus complet.

+0

Cette page de documentation est ce que j'ai cherché en premier, mais ces fonctions _mysql sont la seule chose que cette page mentionne à propos des données d'échappement. Je me souviens très bien du cas terrifiant de Little Bobby Tables: . Que se passe-t-il si Little Bobby Tables apparaît dans MY database? Oh, la terreur! – eje211

+0

Je sais bien que la bonne chose à propos de MySQLdb est que dans l'utilisation normale, il gère l'échappement automatique pour vous, donc il n'y a aucun moyen d'obtenir une injection SQL lorsque vous utilisez l'interface de niveau supérieur. –