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

C++-Runtime UB in TokenStreamRewriter #2740

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

lSoleyl
Copy link

@lSoleyl lSoleyl commented Feb 1, 2020

The pattern:

delete rewrites[iop->instructionIndex];
rewrites[iop->instructionIndex] = nullptr;

was used throughout this method and is undefined behavior because iop and rewrites[iop->instructionIndex] actually refer to the same object and thus the object's fields are accessed after the object itself has been deleted. This has caused crashes in my application, which are fixed by this commit.

I fixed this by rearranging the object deletions to be performed after any code, which still references them.

I also removed the seemingly out of place std::cout << "new rop" << rop << std::endl; statement.

lSoleyl and others added 3 commits February 1, 2020 18:28
 - Operation objects have been accessed after deletion.
 - Removed (debug?) print statement to std::cout when merging two ops.
Copy link
Member

@mike-lischke mike-lischke left a comment

Choose a reason for hiding this comment

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

I'm unsure if that is really a good approach. It requires that rewrites[iop->instructionIndex] is always the same as iop, or put differently: iop doesn't change its position in the rewrites vector. But look at TokenStreamRewriter::rollback where a program is replaced with a new vector that is constructed by copying something out of the existing vector without adjusting the instruction index members.

@lSoleyl
Copy link
Author

lSoleyl commented Apr 8, 2021

Thanks for checking in on this pull request... It is a while ago that I thought about it and at the time of writing I came to the conclusion that this assumption of mine always holds... I might have missed somthing, so please check this thoroughly, but at least rollback doesn't change these position of iop

void TokenStreamRewriter::rollback(const std::string &programName, size_t instructionIndex) {
  std::vector<RewriteOperation*> is = _programs[programName];
  if (is.size() > 0) {
    _programs.insert({ programName, std::vector<RewriteOperation*>(is.begin() + MIN_TOKEN_INDEX, is.begin() + instructionIndex) });
  }
}

It just replaces the vector of operations with a new vector containing only the first n elements, which doesn't change the order or the index of the operations inside the vector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants