Conversation
The test is correct. There is an issue with skip_var_32() that is skipping a number and not checking if they are in range -- that's why it happens during validation. The skip_var_xx logic needs to be fixed. |
| fn read_br_table(&mut self) -> Result<BrTable<'a>> { | ||
| let targets_len = self.read_var_u32()? as usize; | ||
| if targets_len > MAX_WASM_BR_TABLE_SIZE { | ||
| let len_targets = self.read_var_u32()? as usize; |
There was a problem hiding this comment.
wonder why targets_len renamed to len_targets?
There was a problem hiding this comment.
tbh no good reasons. i just personally liked the name better during refactoring. will undo. ;)
| end: usize, | ||
| } | ||
|
|
||
| impl<'a> IntoIterator for &'a BrTable<'a> { |
There was a problem hiding this comment.
I think we can still keep IntoIterator for BrTable: type IntoIter = Chain<BrTableTargets, Once<u32>>?
There was a problem hiding this comment.
We can do that. I just removed it because it is not directly clear what exactly BrTable is iterating over given IntoIterator whereas for types like Vec it is totally clear. So I thought maybe methods are a superior fit in this case and therefore replaced the IntoIterator impl with two methods for each explicit use case.
| // `BrTableTargets` iterator from a proper `BrTable` instance | ||
| // which checks the underlying buffer for being a valid `br_table` | ||
| // entries buffer. | ||
| .expect("expected a `br_table` target var_u32"); |
There was a problem hiding this comment.
We can keep it after skip_var_32 is fixed, though it shall never be raised during testing.
There was a problem hiding this comment.
I wasn't sure if skip_var_32 is actually broken but good to know. :) I think this implementation is actually more robust since it pointed out this potential bug and it shouldn't be a performance hit at all. But we should make sure that this is actually true. Fortunately wasmparser has a decent benchmark suite.
| /// The number of non-default targets of the `br_table`. | ||
| pub(crate) len_targets: usize, | ||
| /// The default target offset of the `br_table`. | ||
| pub default_offset: u32, |
There was a problem hiding this comment.
default_offset -> default_target
Robbepop
left a comment
There was a problem hiding this comment.
From looking at the test snippet it seems to me that the empty-br-table.wasm is actually syntactically incorrect, not semantically so it should fail during parsing, not during validation but I might be wrong here.
The test is correct. There is an issue with skip_var_32() that is skipping a number and not checking if they are in range -- that's why it happens during validation. The skip_var_xx logic needs to be fixed.
Thank you for letting me know. I was really confused. 😅
|
Closed in favor of #216. |
Associated issue: https://github.com/bytecodealliance/wasmparser/issues/174
This PR slightly refactors the
BrTableabstraction of the Wasmbr_table.default_offsettoBrTableIntoIteratorimpl for&'a BrTabletargetsandtargets_and_defaultiterator methods toBrTableBrTableTargets(the iterator type)Let me explain the changes.
br_tablewe simply add it as a field instead of merging it with the other non-default target offsets.IntoIteratorimpl was confusing since it was not clear what exactly is being iterated over (with or without default offset?). So the new interface provides two different methods for those two use cases.nextimplementation fromto
While this might look like a really bad change it actually makes the whole iteration more correct from what I can tell. Please prove me wrong on this because I am actually still a bit confused about what I found: The
empty-br-tabletest broke after this change - note, that every other test of the whole test suite continued to work under this change.From looking at the test snippet it seems to me that the
empty-br-table.wasmis actually syntactically incorrect, not semantically so it should fail during parsing, not during validation but I might be wrong here.Why is the old and super fancy small interface working? Tbh I cannot tell for sure but it obviously is more robust against too small buffers. So the iterator will silently yield less elements than there are which is what is incorrect about it imo. But I am still a bit confused because the
create_br_tablefunction should in theory sort out those malicious cases before they can even exist. Need to dig in deeper.Please tell me if I am completely wrong about my assumptions so far. @yurydelendik