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

Fix a case of using the wrong stack map during gcs #2396

Merged

Conversation

alexcrichton
Copy link
Member

This commit fixes an issue where when looking up the stack map for a pc
within a function we might end up reading the previous function's
stack maps. This then later caused asserts to trip because we started
interpreting random data as a VMExternRef when it wasn't. The fix was
to add None markers for "this range has no stack map" in the function
ranges map.

Closes #2386

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice digging!

r=me modulo dealing with the inline comment below

Comment on lines 808 to 828
// Add a marker between functions indicating that this function's pc
// starts with no stack map so when our binary search later on finds
// a pc between the start of the function and the function's first
// stack map it doesn't think the previous stack map is our stack
// map.
if pc_to_stack_map.len() > 0 {
pc_to_stack_map.push((range.start, None));
}

for info in infos {
assert!((info.code_offset as usize) < len);
pc_to_stack_map.push((
range.start + (info.code_offset as usize),
Rc::new(info.stack_map.clone()),
Some(Rc::new(info.stack_map.clone())),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If info.code_offset is 0 then we could have duplicate entries (one None for the start of the function and one Some for this info).

I don't think this should ever happen though, so perhaps we can just assert that info.code_offset > 0?

The alternative is checking ahead of time whether the first info.code_offset is 0 (because they should be sorted iirc) and only adding the None entry if the first info.code_offset is not 0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice catch, I refactored a bit which I think will handle this correctly, mind double-checking?

I also went ahead and did a small tweak where consecutive None entries are now coalesced.

This commit fixes an issue where when looking up the stack map for a pc
within a function we might end up reading the *previous* function's
stack maps. This then later caused asserts to trip because we started
interpreting random data as a `VMExternRef` when it wasn't. The fix was
to add `None` markers for "this range has no stack map" in the function
ranges map.

Closes bytecodealliance#2386
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

// marker, in which case the starting pc already has no stack map.
// This is also skipped if the first `code_offset` is zero since
// what we'll push applies for the first pc anyway.
if !last_is_none_marker && (infos.is_empty() || infos[0].code_offset > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could make this a tiny bit less wordy (although perhaps some would argue less readable) like this:

Suggested change
if !last_is_none_marker && (infos.is_empty() || infos[0].code_offset > 0) {
if !last_is_none_marker && (infos.get(0).map_or(true, |i| i.code_offset > 0) {

I would probably use map_or personally but it doesn't really matter either way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I guess this isn't actually even less wordy... nevermind!

@alexcrichton alexcrichton merged commit 068340d into bytecodealliance:main Nov 12, 2020
@alexcrichton alexcrichton deleted the use-right-stack-map branch November 12, 2020 19:24
cfallin pushed a commit that referenced this pull request Nov 30, 2020
This commit fixes an issue where when looking up the stack map for a pc
within a function we might end up reading the *previous* function's
stack maps. This then later caused asserts to trip because we started
interpreting random data as a `VMExternRef` when it wasn't. The fix was
to add `None` markers for "this range has no stack map" in the function
ranges map.

Closes #2386
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants