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

Ensure that contents and valid apply to individual elements (not the whole array) #1117

Closed
sc07kvm opened this issue Oct 15, 2020 · 4 comments

Comments

@sc07kvm
Copy link

sc07kvm commented Oct 15, 2020

kaitai-struct-compiler -t python .\kaitai_struct_formats\image\icc_4.ksy

can't compare CalcArrayType(BytesLimitType(IntNum(1),None,false,None,None)) and CalcBytesType

@dgelessus
Copy link
Contributor

Can you try if this still happens with version 0.9 (snapshot) of the compiler? This might have been fixed as part of #719.

@sc07kvm
Copy link
Author

sc07kvm commented Oct 15, 2020

I tried on the latest version

kaitai-struct-compiler --version
kaitai-struct-compiler 0.9-SNAPSHOT

@generalmimon
Copy link
Member

Can you try if this still happens with version 0.9 (snapshot) of the compiler?

I tried on the latest version

Yeah, I also tried it in the devel Web IDE, and the problem is in this situation:

https://github.com/kaitai-io/kaitai_struct_formats/blob/d1e58e36f26ecff1375c6022dc040342914ee4d1/image/icc_4.ksy#L1142-L1145

As you can see in the snippet above, the field padding (among others across the spec) uses contents + repeat. However, judging by the error message (can't compare CalcArrayType(BytesLimitType(IntNum(1),None,false,None,None)) and CalcBytesType), the contents key is interpreted as the expected value of the whole array, not of the individual elements. The entire array stored in attribute padding has indeed the type CalcArrayType(BytesLimitType(IntNum(1),None,false,None,None)), which can be better shown on this equivalent snippet rewritten with the valid key (new in 0.9 - see #435 (comment)):

- id: padding
  size: 1
  valid:
    eq: [0x00]

However, the icc_4.ksy spec compiles fine in the stable 0.8 version of the compiler (and thus also in the stable Web IDE), and the above excerpt compiles to this:

          Colorant.prototype._read = function() {
            //  ... 
            this.padding = new Array((32 - this.name.length));
            for (var i = 0; i < (32 - this.name.length); i++) {
              this.padding = this._io.ensureFixedContents([0]);
            }

In short: contents affected individual elements in 0.8, but valid introduced in 0.9 applies to the entire array, and this has also silently changed the behavior of contents, because it has been internally unified with valid key inside the compiler.

But I don't think this BC break is intentional: it's just that the repetitions are often forgotten/overlooked when implementing a new feature in KS, because sometimes their support requires additional hard work (see what needed to be done for the process key - kaitai-io/kaitai_struct_compiler#198).

So let's add a test into our test suite and make it work again in the KSC, the icc_4.ksy spec is completely fine.

@Artoria2e5
Copy link

The current web IDE is failing too. I guess 0.9 has become stable?

@generalmimon generalmimon transferred this issue from kaitai-io/kaitai_struct_formats Jul 15, 2024
@generalmimon generalmimon changed the title Error while compiling file image/icc_4.ksy Ensure that contents and valid apply to individual elements (not the whole array) Jul 15, 2024
generalmimon added a commit to kaitai-io/kaitai_struct_tests that referenced this issue Jul 16, 2024
generalmimon added a commit to kaitai-io/kaitai_struct_compiler that referenced this issue Jul 16, 2024
This change is a prerequisite to solve
kaitai-io/kaitai_struct#1117. If the
implementation of the `valid` key calls the public accessors to get the
value to validate, modifying the `valid` implementation to apply the
`valid` constraint to individual elements (as required by
kaitai-io/kaitai_struct#1117) causes infinite
recursion in the ValidFailInst test in those languages (C++/STL, C#, Go)
which use flags to remember whether an instance already has a cached
value or not. This is because the public accessor of the instance is
then called from the body of the public accessor itself (recursively),
and the recursion is infinite due to running the `valid` check before
setting the instance flag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants