Skip to content

Commit ccaf602

Browse files
committed
Check integer overflow in long range
https://hackerone.com/reports/1328463
1 parent 45e32ba commit ccaf602

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

ext/cgi/escape/escape.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,21 @@ preserve_original_state(VALUE orig, VALUE dest)
3232
rb_enc_associate(dest, rb_enc_get(orig));
3333
}
3434

35+
static inline long
36+
escaped_length(VALUE str)
37+
{
38+
const long len = RSTRING_LEN(str);
39+
if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
40+
ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
41+
}
42+
return len * HTML_ESCAPE_MAX_LEN;
43+
}
44+
3545
static VALUE
3646
optimized_escape_html(VALUE str)
3747
{
3848
VALUE vbuf;
39-
typedef char escape_buf[HTML_ESCAPE_MAX_LEN];
40-
char *buf = *ALLOCV_N(escape_buf, vbuf, RSTRING_LEN(str));
49+
char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
4150
const char *cstr = RSTRING_PTR(str);
4251
const char *end = cstr + RSTRING_LEN(str);
4352

test/cgi/test_cgi_util.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,23 @@ def test_cgi_escape_html_dont_freeze
104104
assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen?
105105
end
106106

107+
def test_cgi_escape_html_large
108+
ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX")
109+
return unless ulong_max < size_max # Platforms not concerned
110+
111+
size = (ulong_max / 6 + 1)
112+
begin
113+
str = '"' * size
114+
escaped = CGI.escapeHTML(str)
115+
rescue NoMemoryError
116+
omit "Not enough memory"
117+
rescue => e
118+
end
119+
assert_raise_with_message(ArgumentError, /overflow/, ->{"length = #{escaped.length}"}) do
120+
raise e if e
121+
end
122+
end
123+
107124
def test_cgi_unescapeHTML
108125
assert_equal("'&\"><", CGI.unescapeHTML("&#39;&amp;&quot;&gt;&lt;"))
109126
end

0 commit comments

Comments
 (0)