Skip to content

Commit 93f1010

Browse files
committed
Packing the buffer into itself is not possible
Reported at https://hackerone.com/reports/3601645.
1 parent f7a799a commit 93f1010

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

pack.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ typedef union {
119119
#define MAX_INTEGER_PACK_SIZE 8
120120

121121
static const char toofew[] = "too few arguments";
122+
static const char intoitself[] = "cannot pack buffer object into itself";
122123

123124
static void encodes(VALUE,const char*,long,int,int);
124125
static void qpencode(VALUE,VALUE,long);
@@ -280,6 +281,8 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
280281
#define MORE_ITEM (idx < RARRAY_LEN(ary))
281282
#define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW)
282283
#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
284+
#define NOT_BUFFER(val) (((val) == res) ? rb_raise(rb_eArgError, intoitself) : (void)0)
285+
#define STR_FROM(val) NOT_BUFFER(StringValue(val))
283286

284287
while (p < pend) {
285288
int explicit_endian = 0;
@@ -334,7 +337,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
334337
plen = 0;
335338
}
336339
else {
337-
StringValue(from);
340+
STR_FROM(from);
338341
ptr = RSTRING_PTR(from);
339342
plen = RSTRING_LEN(from);
340343
}
@@ -719,7 +722,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
719722
case 'u': /* uuencoded string */
720723
case 'm': /* base64 encoded string */
721724
from = NEXTFROM;
722-
StringValue(from);
725+
STR_FROM(from);
723726
ptr = RSTRING_PTR(from);
724727
plen = RSTRING_LEN(from);
725728

@@ -749,6 +752,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
749752

750753
case 'M': /* quoted-printable encoded string */
751754
from = rb_obj_as_string(NEXTFROM);
755+
NOT_BUFFER(from);
752756
if (len <= 1)
753757
len = 72;
754758
qpencode(res, from, len);
@@ -757,7 +761,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
757761
case 'P': /* pointer to packed byte string */
758762
from = THISFROM;
759763
if (!NIL_P(from)) {
760-
StringValue(from);
764+
STR_FROM(from);
761765
if (RSTRING_LEN(from) < len) {
762766
rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
763767
RSTRING_LEN(from), len);
@@ -767,13 +771,11 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
767771
/* FALL THROUGH */
768772
case 'p': /* pointer to string */
769773
while (len-- > 0) {
770-
char *t;
774+
char *t = 0;
771775
from = NEXTFROM;
772-
if (NIL_P(from)) {
773-
t = 0;
774-
}
775-
else {
776-
t = StringValuePtr(from);
776+
if (!NIL_P(from)) {
777+
STR_FROM(from);
778+
t = RSTRING_PTR(from);
777779
}
778780
if (!associates) {
779781
associates = rb_ary_new();

test/ruby/test_pack.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,19 @@ def test_pack_with_buffer
881881
assert_equal "\xDE\xAD\xBE\xEF\xBA\xBE\xF0\x0D\0\0\xBA\xAD\xFA\xCE", buf
882882

883883
assert_equal addr, [buf].pack('p')
884+
885+
assert_packing_buffer_fail("b*")
886+
assert_packing_buffer_fail("B*")
887+
assert_packing_buffer_fail("h*")
888+
assert_packing_buffer_fail("H*")
889+
assert_packing_buffer_fail("u", 16384)
890+
assert_packing_buffer_fail("m", 16384)
891+
assert_packing_buffer_fail("M", 16384)
892+
end
893+
894+
def assert_packing_buffer_fail(fmt, size = 8192)
895+
s = "\x01".b * size
896+
assert_raise(ArgumentError) {[s].pack(fmt, buffer: s)}
884897
end
885898

886899
def test_unpack_with_block

0 commit comments

Comments
 (0)