[前][次][番号順一覧][スレッド一覧]

ruby-changes:70160

From: Nobuyoshi <ko1@a...>
Date: Sun, 12 Dec 2021 13:05:33 +0900 (JST)
Subject: [ruby-changes:70160] e4b35b158a (master): [ruby/cgi] Check integer overflow in long range

https://git.ruby-lang.org/ruby.git/commit/?id=e4b35b158a

From e4b35b158a16c42d2b91a3e88309875240d0ce27 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Fri, 3 Sep 2021 19:40:22 +0900
Subject: [ruby/cgi] Check integer overflow in long range

https://hackerone.com/reports/1328463

https://github.com/ruby/cgi/commit/ccaf6027e0
---
 ext/cgi/escape/escape.c   | 13 +++++++++++--
 test/cgi/test_cgi_util.rb | 17 +++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index 809f95ef4cc..f88b61478b7 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -32,12 +32,21 @@ preserve_original_state(VALUE orig, VALUE dest) https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L32
     rb_enc_associate(dest, rb_enc_get(orig));
 }
 
+static inline long
+escaped_length(VALUE str)
+{
+    const long len = RSTRING_LEN(str);
+    if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
+	ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
+    }
+    return len * HTML_ESCAPE_MAX_LEN;
+}
+
 static VALUE
 optimized_escape_html(VALUE str)
 {
     VALUE vbuf;
-    typedef char escape_buf[HTML_ESCAPE_MAX_LEN];
-    char *buf = *ALLOCV_N(escape_buf, vbuf, RSTRING_LEN(str));
+    char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
     const char *cstr = RSTRING_PTR(str);
     const char *end = cstr + RSTRING_LEN(str);
 
diff --git a/test/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb
index 6ce8b42c20f..5a2d07b328f 100644
--- a/test/cgi/test_cgi_util.rb
+++ b/test/cgi/test_cgi_util.rb
@@ -104,6 +104,23 @@ class CGIUtilTest < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/cgi/test_cgi_util.rb#L104
     assert_not_predicate CGI.escapeHTML("Ruby".freeze),   :frozen?
   end
 
+  def test_cgi_escape_html_large
+    ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX")
+    return unless ulong_max < size_max # Platforms not concerned
+
+    size = (ulong_max / 6 + 1)
+    begin
+      str = '"' * size
+      escaped = CGI.escapeHTML(str)
+    rescue NoMemoryError
+      omit "Not enough memory"
+    rescue => e
+    end
+    assert_raise_with_message(ArgumentError, /overflow/, ->{"length = #{escaped.length}"}) do
+      raise e if e
+    end
+  end
+
   def test_cgi_unescapeHTML
     assert_equal("'&\"><", CGI.unescapeHTML("&#39;&amp;&quot;&gt;&lt;"))
   end
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]