Skip to content

Commit

Permalink
Skip spaces early so we don't consume more tokens
Browse files Browse the repository at this point in the history
Several new unpack specs were failing because they did not raise
an error for directives like "a 0A". The problem was that because
the handling of the space occurred in the main switch for unpack,
it also caused the "0" to be consumed as an unused occurrence
count. The unpack then proceeded on to the "A" and returned a
result rather than raising.

This change matches CRuby by moving the space check all the way to
the top of the loop, so that spaces are skipped without any
further processing of the next element in the directive.
  • Loading branch information
headius committed Dec 19, 2024
1 parent 3b50df5 commit 85a281b
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions core/src/main/java/org/jruby/util/Pack.java
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,9 @@ private static IRubyObject unpackInternal(ThreadContext context, RubyString enco
mainLoop: while (next != 0) {
int type = next;
next = getDirective(context, "unpack", formatString, format);


if (isSpace(type)) continue;

if (type == '#') {
while (type != '\n') {
if (next == 0) break mainLoop;
Expand Down Expand Up @@ -1094,13 +1096,6 @@ private static IRubyObject unpackInternal(ThreadContext context, RubyString enco
case 'w':
value = unpack_w(context, block, result, encode, occurrences, mode);
break;
case ' ': // various "ok" whitespace
case '\011':
case '\n':
case '\013':
case '\014':
case '\015':
break;
default:
unknownDirective(context, "unpack", type, formatString);
break;
Expand All @@ -1111,6 +1106,15 @@ private static IRubyObject unpackInternal(ThreadContext context, RubyString enco
return result;
}

private static boolean isSpace(int type) {
boolean isSpace = switch (type) {
case ' ', '\011', '\n', '\013', '\014', '\015' -> true;
default -> false;
};
if (isSpace) return true;
return false;
}

private static IRubyObject unpack_w(ThreadContext context, Block block, RubyArray result, ByteBuffer encode, int occurrences, int mode) {
if (occurrences == IS_STAR || occurrences > encode.remaining()) {
occurrences = encode.remaining();
Expand Down

0 comments on commit 85a281b

Please sign in to comment.