Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_root / _parent chain broken by recursive use of the top-level type #1089

Closed
generalmimon opened this issue Mar 15, 2024 · 0 comments · Fixed by kaitai-io/kaitai_struct_compiler#283
Milestone

Comments

@generalmimon
Copy link
Member

If the top-level type is used recursively, _root (and _parent in some target languages) refers to the closest ancestor in the object tree that has the top-level type, not to the actual root of the object tree.

Consider the following .ksy snippet:

meta:
  id: nav_root_recursive
seq:
  - id: value
    type: u1
  - id: next
    type: nav_root_recursive
    if: value != 0x01
instances:
  root_value:
    value: _root.value

If you try this for example on bytes 80 01, you get the following object tree (as of KSC at commit 6aef6fae):

├── value = 0x80 (= 128)
├── next [NavRootRecursive]
│   ├── value = 0x1 (= 1)
│   └── rootValue = 0x1 (= 1)
└── rootValue = 0x80 (= 128)

As you can see, the value of next.rootValue is 1, which indicates that _root in next's context refers to next itself, not the root node of the object tree. _root is not passed from the root object to next, so next falls back to using this as its _root.

This is visible in the generated code, see JavaScript for example:

  NavRootRecursive.prototype._read = function() {
    this.value = this._io.readU1();
    if (this.value != 1) {
      this.next = new NavRootRecursive_.NavRootRecursive(this._io, this, null);
    }
  }

Notice the null being passed as an argument to _root (instead of this._root as usual).

In some languages, the same problem affects not only _root but also _parent - see e.g. Java:

    private void _read() {
        this.value = this._io.readU1();
        if (value() != 1) {
            this.next = new NavRootRecursive(this._io);
        }
    }

The _parent problem can be demonstrated for example as follows (again, this is meant to work on bytes like 80 01, but it can be easily adjusted for pretty much any binary file):

meta:
  id: nav_parent_recursive
seq:
  - id: value
    type: u1
  - id: next
    type: nav_parent_recursive
    if: value == 0x80
instances:
  parent_value:
    value: _parent.as<nav_parent_recursive>.value
    if: value != 0x80

Accessing the next.parent_value instance would fail in Java, since it doesn't pass _parent to invocations of the top-level type (so next._parent would be null).

generalmimon added a commit to kaitai-io/kaitai_struct_tests that referenced this issue Mar 15, 2024
generalmimon added a commit to kaitai-io/kaitai_struct_compiler that referenced this issue Mar 20, 2024
* Fixes kaitai-io/kaitai_struct#1089

  Previously, `_root` and `_parent` weren't passed to the local
  top-level type, which is fixed by this commit.

* Fixes kaitai-io/kaitai_struct#963

  `_root` and `_parent` were incorrectly passed to nested types of
  imported specs (i.e. external types).

  This was demonstrated by asserts in the [KST spec of test
  NestedTypesImport](https://github.com/kaitai-io/kaitai_struct_tests/blob/d07deb4c/spec/ks/nested_types_import.kst#L17-L32).
generalmimon added a commit to kaitai-io/kaitai_struct_compiler that referenced this issue Mar 23, 2024
* Fixes kaitai-io/kaitai_struct#1089

  Previously, `_root` and `_parent` weren't passed to the local
  top-level type, which is fixed by this commit.

* Fixes kaitai-io/kaitai_struct#963

  `_root` and `_parent` were incorrectly passed to nested types of
  imported specs (i.e. external types).

  This was demonstrated by asserts in the [KST spec of test
  NestedTypesImport](https://github.com/kaitai-io/kaitai_struct_tests/blob/d07deb4c/spec/ks/nested_types_import.kst#L17-L32).
generalmimon added a commit to kaitai-io/kaitai_struct_compiler that referenced this issue Mar 30, 2024
* Fixes kaitai-io/kaitai_struct#1089

  Previously, `_root` and `_parent` weren't passed to the local
  top-level type, which is fixed by this commit.

  This was demonstrated by tests NavRootRecursive and NavParentRecursive
  added in kaitai-io/kaitai_struct_tests@5941262e

* Fixes kaitai-io/kaitai_struct#963

  `_root` and `_parent` were incorrectly passed to nested types of
  imported specs (i.e. external types).

  This was demonstrated by asserts in the [KST spec of test
  NestedTypesImport](https://github.com/kaitai-io/kaitai_struct_tests/blob/d07deb4c/spec/ks/nested_types_import.kst#L17-L32).
@GreyCat GreyCat added this to the v0.11 milestone Mar 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants