This is an archive of the discontinued LLVM Phabricator instance.

Check for resource exhaustion when recursively parsing declarators
ClosedPublic

Authored by aaron.ballman on May 4 2022, 5:02 AM.

Details

Summary

With sufficiently tortured code, it's possible to cause a stack overflow when parsing declarators. Thus, we now check for resource exhaustion when recursively parsing declarators so that we can at least warn the user we're about to crash before we actually crash.

This fixes https://github.com/llvm/llvm-project/issues/51642.

Diff Detail

Event Timeline

aaron.ballman created this revision.May 4 2022, 5:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 4 2022, 5:02 AM
aaron.ballman requested review of this revision.May 4 2022, 5:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 4 2022, 5:02 AM
arsenm added a subscriber: arsenm.May 4 2022, 5:03 AM

I think I've seen this one before

Two things to note:

  1. I'm not convinced that adding a test case is the right thing to do here. On the one hand, we want to verify that we now emit the diagnostic before crashing. But on the other hand, this test is extremely expensive to run (because it exhausts the stack) and its behavior is highly specific to the test platform its being run on. If someone asked me to remove the test coverage here, I would not be sad.
  2. The runWithSufficientStackSpace() implementation is a copy of what's already in Sema. I investigated lifting this interface to something more common, but the issue is with generating a diagnostic (there's no common diagnostic engine between Sema and Parser that I could find). Given the simplicity of the implementation, I figured it's reasonably defensible to duplicate the code.
yihanaa added a subscriber: yihanaa.May 4 2022, 5:18 AM

Rebased.

I removed the test coverage because it turned out to not be testing anything. If we exhaust resources, then we don't run the -verify to test the diagnostic behavior, and we're relying on the crash being the test condition, but any crash will suffice.

I don't see how you can test this behavior without figuring out how to get a 'perfect' number to warn but not crash... The only way to validate that I would expect would be to do some bizarre flag that has us just 'don't run' in the case where the warning is emitted, but that would be strange/only used for the test.

Note that I think you might have an improper comment on the Parser::runWithSufficientStackSpace, else we perhaps wish to combine the Sema.cpp and Parser.cpp implementations in some way.

clang/include/clang/Parse/Parser.h
802 ↗(On Diff #428969)

Hmm... The Parser version of this might be used for Template Instantiation? Should we remove the SEMA one and move all uses to the Parser then?

erichkeane added inline comments.May 12 2022, 9:59 AM
clang/lib/Parse/Parser.cpp
2618 ↗(On Diff #428969)

Another concern here: Do we properly initialize "Actions" in the case where we don't have a semantic Action? That is, if we are just preprocessing?

aaron.ballman marked an inline comment as done.May 12 2022, 10:08 AM
aaron.ballman added inline comments.
clang/include/clang/Parse/Parser.h
802 ↗(On Diff #428969)

Nope, but I could be less silly and just... use the one from Sema... instead of moving it to Parser. Derp!

aaron.ballman marked an inline comment as done.

Simplify the implementation by using the facilities Sema already exposes. The behavior remains the same:

F:\source\llvm-project>llvm\out\build\x64-Debug\bin\clang.exe -cc1 -fsyntax-only "C:\Users\aballman\OneDrive - Intel Corporation\Desktop\test.c"
C:\Users\aballman\OneDrive - Intel Corporation\Desktop\test.c:8:1: warning: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely [-Wstack-exhausted]
int PTR6 q3_var = 0;
^
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
erichkeane accepted this revision.May 12 2022, 10:15 AM

Another concern here: Do we properly initialize "Actions" in the case where we don't have a semantic Action? That is, if we are just preprocessing?

Doh! Forgot we don't do 'Parser' in preprocessor mode. LGTM!

This revision is now accepted and ready to land.May 12 2022, 10:15 AM
This revision was landed with ongoing or failed builds.May 12 2022, 10:20 AM
This revision was automatically updated to reflect the committed changes.