Неожиданная замена заполнителя SQL в этом запросе базы данных ruby - PullRequest
2 голосов
/ 27 октября 2011

Может кто-нибудь объяснить, что здесь происходит? Кажется, что синтаксис смещения в строке оператора SQL не работает должным образом (или, говоря иначе, нарушает принцип наименьшего удивления), и во время выполнения для var2 выполняется неожиданная замена / экранирование :

ruby-1.9.2-p290 :001 > puts RUBY_VERSION
1.9.2
 => nil 

ruby-1.9.2-p290 :002 > require 'ipaddr'
=> true 

ruby-1.9.2-p290 :003 > require 'sqlite3'
=> true 

ruby-1.9.2-p290 :004 > var1 = Addrinfo.ip("1.2.3.4")
=> #<Addrinfo: 1.2.3.4> 

ruby-1.9.2-p290 :005 > var2 = var1.ip_address
=> "1.2.3.4" 

ruby-1.9.2-p290 :006 > var3 = "1.2.3.4"
=> "1.2.3.4" 

ruby-1.9.2-p290 :007 > var2 == var3
=> true

ruby-1.9.2-p290 :008 > var2 === var3
=> true

ruby-1.9.2-p290 :009 > var2.eql?(var3)
=> true 

ruby-1.9.2-p290 :010 > db = SQLite3::Database.open( "test.db" )
=> #<SQLite3::Database:0x00000100bcfce0>

ruby-1.9.2-p290 :011 > db.execute( "SELECT * FROM devices WHERE deviceaddr=?", var2 )
=> [] 

ruby-1.9.2-p290 :011 > db.execute( "SELECT * FROM devices WHERE deviceaddr=?", var2.to_s )
=> [] 

ruby-1.9.2-p290 :012 > db.execute( "SELECT * FROM devices WHERE deviceaddr=?", var3 )
=> [["TEST_DEVICE", "1.2.3.4"]] 

Без заполнителя SQL это работает (но подвергает БД SQL-инъекциям!):

ruby-1.9.2-p290 :013 > db.execute( "SELECT * FROM devices WHERE deviceaddr='#{var2}'" )
=> [["TEST_DEVICE", "1.2.3.4"]] 

Так, как безопасный способ заставить это работать?

1 Ответ

4 голосов
/ 27 октября 2011

TL; DR: SQLite использует UTF;преобразовать 8-битный ASCII-вывод Addrinfo.

Один "безопасный" способ - использовать force_encoding("UTF-8") на выходе из Addrinfo, поэтому:

> var1.ip_address.encoding
 => #<Encoding:ASCII-8BIT> 
> var3.encoding
 => #<Encoding:UTF-8> 
> db.execute("SELECT * FROM foo WHERE ip=?", var2.force_encoding("UTF-8"))
 => [["1.2.3.4"]] 
...