Skip to content

Commit f0f11bd

Browse files
committed
[Feature #21979] Allow negative offset in unpack
1 parent 3319be0 commit f0f11bd

2 files changed

Lines changed: 11 additions & 8 deletions

File tree

pack.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,9 +1022,10 @@ pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
10221022
StringValue(fmt);
10231023
rb_must_asciicompat(fmt);
10241024

1025-
if (offset < 0) rb_raise(rb_eArgError, "offset can't be negative");
10261025
len = RSTRING_LEN(str);
1027-
if (offset > len) rb_raise(rb_eArgError, "offset outside of string");
1026+
if (offset < 0 ? (offset += len) < 0 : offset > len) {
1027+
rb_raise(rb_eArgError, "offset outside of string");
1028+
}
10281029

10291030
s = RSTRING_PTR(str);
10301031
send = s + len;

test/ruby/test_pack.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -900,27 +900,29 @@ def test_unpack1
900900

901901
def test_unpack1_offset
902902
assert_equal 65, "ZA".unpack1("C", offset: 1)
903+
assert_equal 65, "ZA".unpack1("C", offset: -1)
903904
assert_equal "01000001", "YZA".unpack1("B*", offset: 2)
904905
assert_nil "abc".unpack1("C", offset: 3)
905-
assert_raise_with_message(ArgumentError, /offset can't be negative/) {
906-
"a".unpack1("C", offset: -1)
907-
}
908906
assert_raise_with_message(ArgumentError, /offset outside of string/) {
909907
"a".unpack1("C", offset: 2)
910908
}
909+
assert_raise_with_message(ArgumentError, /offset outside of string/) {
910+
"a".unpack1("C", offset: -2)
911+
}
911912
assert_nil "a".unpack1("C", offset: 1)
912913
end
913914

914915
def test_unpack_offset
915916
assert_equal [65], "ZA".unpack("C", offset: 1)
917+
assert_equal [65], "ZA".unpack("C", offset: -1)
916918
assert_equal ["01000001"], "YZA".unpack("B*", offset: 2)
917919
assert_equal [nil, nil, nil], "abc".unpack("CCC", offset: 3)
918-
assert_raise_with_message(ArgumentError, /offset can't be negative/) {
919-
"a".unpack("C", offset: -1)
920-
}
921920
assert_raise_with_message(ArgumentError, /offset outside of string/) {
922921
"a".unpack("C", offset: 2)
923922
}
923+
assert_raise_with_message(ArgumentError, /offset outside of string/) {
924+
"a".unpack("C", offset: -2)
925+
}
924926
assert_equal [nil], "a".unpack("C", offset: 1)
925927
end
926928

0 commit comments

Comments
 (0)