-
Notifications
You must be signed in to change notification settings - Fork 1.9k
C++: Generate IR for assertions in release builds #21142
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
base: main
Are you sure you want to change the base?
Conversation
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Fixed
Show fixed
Hide fixed
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Fixed
Show fixed
Hide fixed
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Fixed
Show fixed
Hide fixed
0cf33ff to
20c0239
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for generating IR for assertions in C++ release builds where they would normally be compiled out. The implementation parses macro arguments from assertion macros (like assert and __analysis_assume) to synthesize the conditional checks that would have been present in debug builds, helping CodeQL remove false positives by understanding assertion constraints.
Changes:
- Adds new
TranslatedAssertion.qllmodule that parses assertion macro arguments and generates synthetic IR for simple comparisons - Updates
TranslatedStmt.qllandTranslatedElement.qllto exclude assertion statements from normal translation - Adds new instruction tags and test coverage for assertion IR generation
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll | New module implementing assertion parsing and IR generation for simple comparison assertions |
| cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll | Excludes assertion statements from normal translation to avoid duplication |
| cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll | Integrates assertion translation into the element translation framework |
| cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll | Adds four new instruction tags for assertion IR generation |
| cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll | Adds override for getEnclosingFunction() in StmtParent base class |
| cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll | Adds override keyword to getEnclosingFunction() |
| cpp/ql/lib/semmle/code/cpp/Element.qll | Adds new isAffectedByMacro(MacroInvocation) predicate |
| cpp/ql/test/library-tests/ir/ir/ir.cpp | Adds test cases for assertion IR generation including templates and shadowed variables |
| cpp/ql/test/library-tests/ir/ir/raw_ir.expected | Expected IR output for assertion tests |
| cpp/ql/test/library-tests/ir/ir/aliased_ir.expected | Expected aliased IR output for assertion tests |
| cpp/ql/test/library-tests/ir/ir/PrintAST.expected | Expected AST output for assertion tests |
Comments suppressed due to low confidence (1)
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll:330
- The comment has a typo: "synthedsize" should be "synthesize".
// we synthedsize the check that would have occurred.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Show resolved
Hide resolved
| // An assertion macro invocation typically expand to the | ||
| // expression `((void)0)` in release builds. In that case | ||
| // we synthedsize the check that would have occurred. |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment has a grammar issue: "typically expand" should be "typically expands" to agree with the singular subject "An assertion macro invocation".
| // An assertion macro invocation typically expand to the | |
| // expression `((void)0)` in release builds. In that case | |
| // we synthedsize the check that would have occurred. | |
| // An assertion macro invocation typically expands to the | |
| // expression `((void)0)` in release builds. In that case | |
| // we synthesize the check that would have occurred. |
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Show resolved
Hide resolved
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Show resolved
Hide resolved
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Outdated
Show resolved
Hide resolved
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Show resolved
Hide resolved
4370bc6 to
4f4baee
Compare
In C/C++, assertions are often done via a macro defined like:
where
/* implementation defined */represents the actual operation that implements the assertion in a debug build.However, in a release build (i.e., when
NDEBUGis defined) then no check is performed. This is great for performance, but it means the CodeQL database has no way of observing these conditions. And these conditions often help us remove FPs (i.e., a null check or an index validation prior to a dereference).This PR adds support for identifying (a small subset of) assertions by generating IR corresponding to the check which would have been performed had assertions been enabled (the rationale being basically the same as what Schack wrote for Java here).
This PR only covers a small subset of assertions since we only have the assertion as text since this is a macro argument. So we have to parse that macro argument in QL 😭. Because of this, I've limited this PR to only genearte IR for an assertion of the form
E op EwhereEis an integer constant, or a local variable, andopis=,!=,<,>,<=, or>=. (Locally, I have a follow-up PR to add support for negations, disjunctions, and conjunctions.)As I didn't feel like implementing all of C++'s conversion rules the generated IR will also not be totally conversion-correct. For example, in an expression like
x < ywherexisintandyisunsigned intthere would normally be a signed-to-unsigned conversion onxbut currently we simply generate a comparison between types of different types. I don't imagine this will be a problem in practice, though.Commit-by-commit review recommended.
The three new alerts look genuine. They arise because we now realize that there's a suspicious looking assertion here which ought to have been
fhSize < dstCapacity.