fix CVE-2022-44566 CVE-2023-22794 (cherry picked from commit ead83c6d23c77103756b10a0ec6501a8a5601c52)
133 lines
5.3 KiB
Diff
133 lines
5.3 KiB
Diff
From 4f44aa9d514e701ada92b5cf08beccf566eeaebf Mon Sep 17 00:00:00 2001
|
|
From: Zack Deveau <zack.ref@gmail.com>
|
|
Date: Tue, 22 Nov 2022 09:48:59 -0500
|
|
Subject: [PATCH] Added integer width check to PostgreSQL::Quoting
|
|
|
|
Given a value outside the range for a 64bit signed integer type
|
|
PostgreSQL will treat the column type as numeric. Comparing
|
|
integer values against numeric values can result in a slow
|
|
sequential scan.
|
|
|
|
This behavior is configurable via
|
|
ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.
|
|
|
|
[CVE-2022-44566]
|
|
---
|
|
.../connection_adapters/postgresql/quoting.rb | 26 +++++++++++++++++
|
|
activerecord/lib/active_record/core.rb | 7 +++++
|
|
.../cases/adapters/postgresql/quoting_test.rb | 28 +++++++++++++++++++
|
|
3 files changed, 78 insertions(+)
|
|
|
|
diff --git a/activerecord-6.1.4.1/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord-6.1.4.1/lib/active_record/connection_adapters/postgresql/quoting.rb
|
|
index 3d94d4bb36..4db5f8f528 100644
|
|
--- a/activerecord-6.1.4.1/lib/active_record/connection_adapters/postgresql/quoting.rb
|
|
+++ b/activerecord-6.1.4.1/lib/active_record/connection_adapters/postgresql/quoting.rb
|
|
@@ -4,6 +4,12 @@
|
|
module ConnectionAdapters
|
|
module PostgreSQL
|
|
module Quoting
|
|
+ class IntegerOutOf64BitRange < StandardError
|
|
+ def initialize(msg)
|
|
+ super(msg)
|
|
+ end
|
|
+ end
|
|
+
|
|
# Escapes binary strings for bytea input to the database.
|
|
def escape_bytea(value)
|
|
@connection.escape_bytea(value) if value
|
|
@@ -120,7 +126,27 @@ def lookup_cast_type(sql_type)
|
|
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
|
|
end
|
|
|
|
+ def check_int_in_range(value)
|
|
+ if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
|
|
+ exception = <<~ERROR
|
|
+ Provided value outside of the range of a signed 64bit integer.
|
|
+
|
|
+ PostgreSQL will treat the column type in question as a numeric.
|
|
+ This may result in a slow sequential scan due to a comparison
|
|
+ being performed between an integer or bigint value and a numeric value.
|
|
+
|
|
+ To allow for this potentially unwanted behavior, set
|
|
+ ActiveRecord::Base.raise_int_wider_than_64bit to false.
|
|
+ ERROR
|
|
+ raise IntegerOutOf64BitRange.new exception
|
|
+ end
|
|
+ end
|
|
+
|
|
def _quote(value)
|
|
+ if ActiveRecord::Base.raise_int_wider_than_64bit && value.is_a?(Integer)
|
|
+ check_int_in_range(value)
|
|
+ end
|
|
+
|
|
case value
|
|
when OID::Xml::Data
|
|
"xml '#{quote_string(value.to_s)}'"
|
|
diff --git a/activerecord-6.1.4.1/lib/active_record/core.rb b/activerecord-6.1.4.1/lib/active_record/core.rb
|
|
index 9f1584d46b..d3bfd4929e 100644
|
|
--- a/activerecord-6.1.4.1/lib/active_record/core.rb
|
|
+++ b/activerecord-6.1.4.1/lib/active_record/core.rb
|
|
@@ -163,6 +163,13 @@ def self.configurations
|
|
# to Psych safe_load in the YAML Coder
|
|
mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
|
|
|
|
+ ##
|
|
+ # :singleton-method:
|
|
+ # Application configurable boolean that denotes whether or not to raise
|
|
+ # an exception when the PostgreSQLAdapter is provided with an integer that is
|
|
+ # wider than signed 64bit representation
|
|
+ mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true
|
|
+
|
|
self.filter_attributes = []
|
|
|
|
def self.connection_handler
|
|
diff --git a/test/cases/adapters/postgresql/quoting_test.rb b/test/cases/adapters/postgresql/quoting_test.rb
|
|
index d571355a9c..125565f9c8 100644
|
|
--- a/test/cases/adapters/postgresql/quoting_test.rb
|
|
+++ b/test/cases/adapters/postgresql/quoting_test.rb
|
|
@@ -8,6 +8,7 @@
|
|
class QuotingTest < ActiveRecord::PostgreSQLTestCase
|
|
def setup
|
|
@conn = ActiveRecord::Base.connection
|
|
+ @raise_int_wider_than_64bit = ActiveRecord::Base.raise_int_wider_than_64bit
|
|
end
|
|
|
|
def test_type_cast_true
|
|
@@ -44,6 +45,33 @@ def test_quote_table_name_with_spaces
|
|
value = "user posts"
|
|
assert_equal "\"user posts\"", @conn.quote_table_name(value)
|
|
end
|
|
+
|
|
+ def test_raise_when_int_is_wider_than_64bit
|
|
+ value = 9223372036854775807 + 1
|
|
+ assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
|
|
+ @conn.quote(value)
|
|
+ end
|
|
+
|
|
+ value = -9223372036854775808 - 1
|
|
+ assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
|
|
+ @conn.quote(value)
|
|
+ end
|
|
+ end
|
|
+
|
|
+ def test_do_not_raise_when_int_is_not_wider_than_64bit
|
|
+ value = 9223372036854775807
|
|
+ assert_equal "9223372036854775807", @conn.quote(value)
|
|
+
|
|
+ value = -9223372036854775808
|
|
+ assert_equal "-9223372036854775808", @conn.quote(value)
|
|
+ end
|
|
+
|
|
+ def test_do_not_raise_when_raise_int_wider_than_64bit_is_false
|
|
+ ActiveRecord::Base.raise_int_wider_than_64bit = false
|
|
+ value = 9223372036854775807 + 1
|
|
+ assert_equal "9223372036854775808", @conn.quote(value)
|
|
+ ActiveRecord::Base.raise_int_wider_than_64bit = @raise_int_wider_than_64bit
|
|
+ end
|
|
end
|
|
end
|
|
end
|
|
--
|
|
2.35.1
|
|
|