Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/topic/robin/gh-1842-offset'
Browse files Browse the repository at this point in the history
* origin/topic/robin/gh-1842-offset:
  Fix when input redirection becomes visible.
  • Loading branch information
rsmmr committed Sep 30, 2024
2 parents e4a028a + 2eeffa6 commit a9b78d0
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 9 deletions.
9 changes: 9 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
1.12.0-dev.116 | 2024-09-30 13:35:49 +0200

* GH-1842: Fix when input redirection becomes visible. (Robin Sommer, Corelight)

With `&parse-at/from` we were updating the internal state on our
current position immediately, meaning they were visible already when
evaluating other attributes on the same field afterwards, which is
unexpected.

1.12.0-dev.114 | 2024-09-30 10:24:42 +0200

* GH-1844: Fix nested look-ahead parsing. (Robin Sommer, Corelight)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.12.0-dev.114
1.12.0-dev.116
5 changes: 2 additions & 3 deletions doc/autogen/types/unit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,13 @@
Returns the offset of the current location in the input stream
relative to the unit's start. If executed from inside a field hook,
the offset will represent the first byte that the field has been
parsed from.
the offset will represent the beginning of the field, not the end.

.. spicy:method:: unit::position unit position False iterator<stream> ()
Returns an iterator to the current position in the unit's input
stream. If executed from inside a field hook, the position will
represent the first byte that the field has been parsed from.
represent the beginning of the field, not the end.

.. spicy:method:: unit::set_input unit set_input False void (i: iterator<stream>)
Expand Down
6 changes: 3 additions & 3 deletions spicy/toolchain/src/ast/operators/unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class Offset : public hilti::BuiltInMemberCall {
.doc = R"(
Returns the offset of the current location in the input stream relative to the
unit's start. If executed from inside a field hook, the offset will represent
the first byte that the field has been parsed from.
the beginning of the field, not the end.
)",
};
}
Expand All @@ -212,8 +212,8 @@ class Position : public hilti::BuiltInMemberCall {
.ns = "unit",
.doc = R"(
Returns an iterator to the current position in the unit's input stream. If
executed from inside a field hook, the position will represent the first byte
that the field has been parsed from.
executed from inside a field hook, the position will represent the beginning of
the field, not the end.
)",
};
}
Expand Down
3 changes: 1 addition & 2 deletions spicy/toolchain/src/compiler/codegen/parser-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ struct ProductionVisitor : public production::Visitor {
auto etype = c->parseType()->type()->elementType();
auto container_element = builder()->addTmp("elem", etype);
pushDestination(container_element);
pb->saveParsePosition(); // need to update position for container elements in case input is redirected
}

else if ( ! meta.isFieldProduction() )
Expand Down Expand Up @@ -1430,7 +1431,6 @@ struct ProductionVisitor : public production::Visitor {
pstate.cur = builder()->addTmp("parse_cur", builder()->typeStreamView(), builder()->deref(tmp));
pstate.ncur = {};
pushState(std::move(pstate));
pb->saveParsePosition();
}

// Redirects input to be read from given stream position next.
Expand All @@ -1446,7 +1446,6 @@ struct ProductionVisitor : public production::Visitor {
pstate.cur = builder()->addTmp("parse_cur", cur);
pstate.ncur = {};
pushState(std::move(pstate));
pb->saveParsePosition();
}

// Start sync and trial mode.
Expand Down
5 changes: 5 additions & 0 deletions tests/Baseline/spicy.types.unit.size-with-offset/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
x, 3
x, \x01\x02\x03
z, 4
z, 1234
18 changes: 18 additions & 0 deletions tests/spicy/types/unit/offset-with-parse.spicy
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# @TEST-EXEC: printf 'a' | spicy-driver -d %INPUT
#
# @TEST-DOC:

module Test;

public type X = unit {
a: bytes &size=1;

y1: Y &parse-at=self.input();
y2: Y &parse-from=self.a; # Behaves identical.
};

type Y = unit {
a: bytes &size=1 {
assert self.offset() == 0 : "First element should always be at offset 0";
}
};
30 changes: 30 additions & 0 deletions tests/spicy/types/unit/size-with-offset.spicy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# @TEST-EXEC: ${SCRIPTS}/printf '\x01\x02\x03\x04\0x05' | spicy-driver %INPUT >output
# @TEST-EXEC: btest-diff output
#
# @TEST-EXED: Check that changing the input with `&parse-at` isn't visible to other attributes on same field; regression test for #1842.

module Test;

import spicy;

public type X = unit {
a: uint8;
b: uint8;
c: uint8;

x: bytes &size=self.offset() # yields 3
&parse-at=self.input() {
print "x", self.offset(); # yields still 3
print "x", $$;
}

y: uint8;

z: bytes &size=self.offset() # yields 4
&parse-from=b"12345" {
print "z", self.offset(); # yields still 4
print "z", $$;
}

d: uint8;
};

0 comments on commit a9b78d0

Please # to comment.