summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--pack.c10
-rw-r--r--test/ruby/test_pack.rb19
3 files changed, 30 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index eb4a635..fdaf4d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sun Dec 13 18:33:41 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * pack.c (pack_pack): always check index range against the
+ receiver array length, which can be shortened by elements
+ conversion. reported by Marcin 'Icewall' Noga of Cisco Talos.
+
Sun Dec 13 18:28:52 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/psych/psych_emitter.c (start_document): should not exceed
diff --git a/pack.c b/pack.c
index f47423a..9b4aa6a 100644
--- a/pack.c
+++ b/pack.c
@@ -361,7 +361,7 @@ pack_pack(VALUE ary, VALUE fmt)
const char *p, *pend;
VALUE res, from, associates = 0;
char type;
- long items, len, idx, plen;
+ long len, idx, plen;
const char *ptr;
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
#ifdef NATINT_PACK
@@ -374,12 +374,12 @@ pack_pack(VALUE ary, VALUE fmt)
pend = p + RSTRING_LEN(fmt);
res = rb_str_buf_new(0);
- items = RARRAY_LEN(ary);
idx = 0;
#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
-#define THISFROM (items > 0 ? RARRAY_AREF(ary, idx) : TOO_FEW)
-#define NEXTFROM (items-- > 0 ? RARRAY_AREF(ary, idx++) : TOO_FEW)
+#define MORE_ITEM (idx < RARRAY_LEN(ary))
+#define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW)
+#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
while (p < pend) {
int explicit_endian = 0;
@@ -431,7 +431,7 @@ pack_pack(VALUE ary, VALUE fmt)
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0
: strchr("PMm", type) ? 1
- : items;
+ : RARRAY_LEN(ary) - idx;
p++;
}
else if (ISDIGIT(*p)) {
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index 8dbfd95..d696dd7 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -794,4 +794,23 @@ EXPECTED
}
}
end
+
+ def test_pack_resize
+ assert_separately([], <<-'end;')
+ ary = []
+ obj = Class.new {
+ define_method(:to_str) {
+ ary.clear()
+ ary = nil
+ GC.start
+ "TALOS"
+ }
+ }.new
+
+ ary.push(obj)
+ ary.push(".")
+
+ assert_raise_with_message(ArgumentError, /too few/) {ary.pack("AA")}
+ end;
+ end
end