summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--array.c13
-rw-r--r--test/ruby/test_array.rb28
-rw-r--r--version.h6
4 files changed, 51 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f6ef6507d..bbb2910a5d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Tue Aug 4 03:13:59 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (ary_ensure_room_for_push): check if array size will
+ exceed maximum size to get rid of buffer overflow.
+ [ruby-dev:49043] [Bug #11235]
+
+ * array.c (ary_ensure_room_for_unshift, rb_ary_splice): ditto.
+
Sat Jul 4 23:08:32 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* file.c (rb_file_load_ok): try opening file without gvl not to
diff --git a/array.c b/array.c
index 6babe97ef9..82a4d359ab 100644
--- a/array.c
+++ b/array.c
@@ -353,9 +353,13 @@ rb_ary_modify(VALUE ary)
static VALUE
ary_ensure_room_for_push(VALUE ary, long add_len)
{
- long new_len = RARRAY_LEN(ary) + add_len;
+ long old_len = RARRAY_LEN(ary);
+ long new_len = old_len + add_len;
long capa;
+ if (old_len > ARY_MAX_SIZE - add_len) {
+ rb_raise(rb_eIndexError, "index %ld too big", new_len);
+ }
if (ARY_SHARED_P(ary)) {
if (new_len > RARRAY_EMBED_LEN_MAX) {
VALUE shared = ARY_SHARED(ary);
@@ -1088,6 +1092,10 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
long capa;
const VALUE *head, *sharedp;
+ if (len > ARY_MAX_SIZE - argc) {
+ rb_raise(rb_eIndexError, "index %ld too big", new_len);
+ }
+
if (ARY_SHARED_P(ary)) {
VALUE shared = ARY_SHARED(ary);
capa = RARRAY_LEN(shared);
@@ -1585,6 +1593,9 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
else {
long alen;
+ if (olen - len > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
+ }
rb_ary_modify(ary);
alen = olen + rlen - len;
if (alen >= ARY_CAPA(ary)) {
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 0a4b1379f1..8c8b63c4e2 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -2496,6 +2496,34 @@ class TestArray < Test::Unit::TestCase
end
end
+ sizeof_long = [0].pack("l!").size
+ sizeof_voidp = [""].pack("p").size
+ if sizeof_long < sizeof_voidp
+ ARY_MAX = (1<<(8*sizeof_long-1)) / sizeof_voidp - 1
+ Bug11235 = '[ruby-dev:49043] [Bug #11235]'
+
+ def test_push_over_ary_max
+ assert_separately(['-', ARY_MAX.to_s, Bug11235], <<-"end;")
+ a = Array.new(ARGV[0].to_i)
+ assert_raise(IndexError, ARGV[1]) {0x1000.times {a.push(1)}}
+ end;
+ end
+
+ def test_unshift_over_ary_max
+ assert_separately(['-', ARY_MAX.to_s, Bug11235], <<-"end;")
+ a = Array.new(ARGV[0].to_i)
+ assert_raise(IndexError, ARGV[1]) {0x1000.times {a.unshift(1)}}
+ end;
+ end
+
+ def test_splice_over_ary_max
+ assert_separately(['-', ARY_MAX.to_s, Bug11235], <<-"end;")
+ a = Array.new(ARGV[0].to_i)
+ assert_raise(IndexError, ARGV[1]) {a[0, 0] = Array.new(0x1000)}
+ end;
+ end
+ end
+
private
def need_continuation
unless respond_to?(:callcc, true)
diff --git a/version.h b/version.h
index 46fc75ad4e..243b8e5b87 100644
--- a/version.h
+++ b/version.h
@@ -1,9 +1,9 @@
#define RUBY_VERSION "2.2.3"
-#define RUBY_RELEASE_DATE "2015-07-04"
-#define RUBY_PATCHLEVEL 147
+#define RUBY_RELEASE_DATE "2015-08-04"
+#define RUBY_PATCHLEVEL 148
#define RUBY_RELEASE_YEAR 2015
-#define RUBY_RELEASE_MONTH 7
+#define RUBY_RELEASE_MONTH 8
#define RUBY_RELEASE_DAY 4
#include "ruby/version.h"