1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Handle broken encoding in #write_query?

If the SQL encoding somehow is invalid, `Regexp#match?` raises `ArgumentError`.

Best we can do is to copy the string and try to match
the regexp in "binary" mode.

Hopefully these cases are rare enough that the string copy
should be an important overhead.
This commit is contained in:
Jean Boussier 2021-12-09 19:06:11 +01:00
parent 86100a1ebf
commit b629a5bc42
5 changed files with 26 additions and 1 deletions

View file

@ -68,7 +68,7 @@ module ActiveRecord
def self.build_read_query_regexp(*parts) # :nodoc:
parts += DEFAULT_READ_QUERY
parts = parts.map { |part| /#{part}/i }
/\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
/\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/n
end
def self.quoted_column_names # :nodoc:

View file

@ -26,6 +26,8 @@ module ActiveRecord
def write_query?(sql) # :nodoc:
!READ_QUERY.match?(sql)
rescue ArgumentError # Invalid encoding
!READ_QUERY.match?(sql.b)
end
def explain(arel, binds = [])

View file

@ -28,6 +28,8 @@ module ActiveRecord
def write_query?(sql) # :nodoc:
!READ_QUERY.match?(sql)
rescue ArgumentError # Invalid encoding
!READ_QUERY.match?(sql.b)
end
# Executes an SQL statement, returning a PG::Result object on success

View file

@ -11,6 +11,8 @@ module ActiveRecord
def write_query?(sql) # :nodoc:
!READ_QUERY.match?(sql)
rescue ArgumentError # Invalid encoding
!READ_QUERY.match?(sql.b)
end
def explain(arel, binds = [])

View file

@ -51,6 +51,25 @@ module ActiveRecord
end
end
if current_adapter?(:PostgreSQLAdapter)
def test_doesnt_error_when_a_select_query_has_encoding_errors
ActiveRecord::Base.while_preventing_writes do
# Contrary to other adapters, Postgres will eagerly fail on encoding errors.
# But at least we can assert it fails in the client and not before when trying to
# match the query.
assert_raises ActiveRecord::StatementInvalid do
@connection.select_all("SELECT '\xC8'")
end
end
end
else
def test_doesnt_error_when_a_select_query_has_encoding_errors
ActiveRecord::Base.while_preventing_writes do
@connection.select_all("SELECT '\xC8'")
end
end
end
def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes
@connection.insert("INSERT INTO subscribers(nick) VALUES ('138853948594')")