mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
C++: Exclusion rules for system macros
Unwanted results were reported for our JPL Rule 24 queries. Including system headers with complex macros could lead to unpredictable alerts from these rules.
This commit is contained in:
@@ -81,8 +81,8 @@ predicate functionContainsPreprocCode(Function f) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a macro definition, as opposed
|
||||
* to being passed in as an argument.
|
||||
* Holds if `e` is completely or partially from a macro invocation `mi`, as
|
||||
* opposed to being passed in as an argument.
|
||||
*
|
||||
* In the following example, the call to `f` is from a macro definition,
|
||||
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
|
||||
@@ -93,8 +93,8 @@ predicate functionContainsPreprocCode(Function f) {
|
||||
* M(y + 1);
|
||||
* ```
|
||||
*/
|
||||
predicate isFromMacroDefinition(Element e) {
|
||||
exists(MacroInvocation mi, Location eLocation, Location miLocation |
|
||||
private predicate isFromMacroInvocation(Element e, MacroInvocation mi) {
|
||||
exists(Location eLocation, Location miLocation |
|
||||
mi.getAnExpandedElement() = e and
|
||||
eLocation = e.getLocation() and
|
||||
miLocation = mi.getLocation() and
|
||||
@@ -109,3 +109,39 @@ predicate isFromMacroDefinition(Element e) {
|
||||
eLocation.getEndColumn() >= miLocation.getEndColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a macro definition, as opposed
|
||||
* to being passed in as an argument.
|
||||
*
|
||||
* In the following example, the call to `f` is from a macro definition,
|
||||
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
|
||||
* from `M` refers to a macro.
|
||||
* ```
|
||||
* #define M(x) f(x)
|
||||
* ...
|
||||
* M(y + 1);
|
||||
* ```
|
||||
*/
|
||||
predicate isFromMacroDefinition(Element e) {
|
||||
isFromMacroInvocation(e, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a _system macro_ definition, as
|
||||
* opposed to being passed in as an argument. A system macro is a macro whose
|
||||
* definition is outside the source directory of the database.
|
||||
*
|
||||
* If the system macro is invoked through a non-system macro, then this
|
||||
* predicate does not hold. That's a limitation of how macros are represented
|
||||
* in the database.
|
||||
*
|
||||
* See also `isFromMacroDefinition`.
|
||||
*/
|
||||
predicate isFromSystemMacroDefinition(Element e) {
|
||||
exists(MacroInvocation mi |
|
||||
isFromMacroInvocation(e, mi) and
|
||||
// Has no relative path in the database, meaning it's a system file.
|
||||
not exists(mi.getMacro().getFile().getRelativePath())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
class OneLineStmt extends Stmt {
|
||||
OneLineStmt() {
|
||||
@@ -34,5 +35,8 @@ where
|
||||
other.onLine(f, line) and toMin = other.getLocation().getStartColumn()
|
||||
|
|
||||
toMin
|
||||
)
|
||||
) and
|
||||
// Exclude statements that are from invocations of system-header macros.
|
||||
// Example: FD_ISSET from glibc.
|
||||
not isFromSystemMacroDefinition(o)
|
||||
select o, "This line contains " + cnt + " statements; only one is allowed."
|
||||
|
||||
@@ -10,11 +10,15 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
from DeclStmt d
|
||||
where
|
||||
exists(Variable v1, Variable v2 | v1 = d.getADeclaration() and v2 = d.getADeclaration() |
|
||||
v1 != v2 and
|
||||
v1.getLocation().getStartLine() = v2.getLocation().getStartLine()
|
||||
)
|
||||
) and
|
||||
// Exclude declarations that are from invocations of system-header macros.
|
||||
// Example: FD_ZERO from glibc.
|
||||
not isFromSystemMacroDefinition(d)
|
||||
select d, "Multiple variable declarations on the same line."
|
||||
|
||||
Reference in New Issue
Block a user