To completely eliminate use-after-free in this place I had to copy tokens into new array and pass ownership. As far as I understand the code it is not possible to guarantee that all inserted tokens are consumed before exiting from this function. Depending on how many tokens were consumed before SkipUntil is called, it may not happen due to unbalanced brackets, etc. Other places where EnterTokenStream is called usually pass vector that some class owns but here it is not possible because this place can be called recursively.
Details
Diff Detail
Event Timeline
I don't fully understand your explanation. Is your change introducing a
memory leak? (or was the old code causing a double free (if
EnterTokenStream does take ownership of this argument)in addition to
use-after-free?)
I didn't introduce a leak because I pass ownership of the Buffer to EnterTokenStream (i.e. pass true as the last argument OwnsTokens). ASan also doesn't report a leak with my patch. Original code didn't have double free because it used call EnterTokenStream with OwnsTokens == false.
I believe this change is correct but I believe we can handle this a little more efficiently.
I wonder if it would be better if we instead inserted a special EOF token at the end of Toks. If any errors occur, consume tokens until we hit our special EOF token. ParseLexedAttribute and ParseLexedMethodDeclaration follow this pattern. To make it a little more obvious that the lifetime of Toks is somehow tied to EnterTokenStream and the parsing code that follows, it might make sense to factor the code after EnterTokenStream into another function.
Use EOF token instead of copy buffer. This approach looks a bit more fragile but definitely more efficient, PTAL.