Skip to content

Commit bef5a36

Browse files
committed
PRE31-C: Refactor to create UnsafeMacroInvocation
Refactor the query to create a separate class for representing unsafe macro invocations. This will enable the query to be improved by determining whether we actually observe multiple side-effects in practice (to handle cases like `type(e) = e;`.
1 parent d6a4c4e commit bef5a36

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,28 +65,49 @@ class UnsafeMacro extends FunctionLikeMacro {
6565
int getAnUnsafeArgumentIndex() { result = unsafeArgumentIndex }
6666
}
6767

68+
/**
69+
* An invocation of a potentially unsafe macro.
70+
*/
71+
class UnsafeMacroInvocation extends MacroInvocation {
72+
UnsafeMacroInvocation() {
73+
this.getMacro() instanceof UnsafeMacro and not exists(this.getParentInvocation())
74+
}
75+
76+
/**
77+
* Gets a side-effect for a potentially unsafe argument to the macro.
78+
*/
79+
SideEffect getSideEffectForUnsafeArg(int index) {
80+
index = this.getMacro().(UnsafeMacro).getAnUnsafeArgumentIndex() and
81+
exists(Expr e, string arg |
82+
arg = this.getExpandedArgument(index) and
83+
e = this.getAnExpandedElement() and
84+
result = getASideEffect(e) and
85+
(
86+
result instanceof CrementEffect and
87+
exists(arg.indexOf(result.(CrementOperation).getOperator()))
88+
or
89+
result instanceof FunctionCallEffect and
90+
exists(arg.indexOf(result.(FunctionCall).getTarget().getName() + "("))
91+
)
92+
)
93+
}
94+
}
95+
6896
from
69-
UnsafeMacro flm, MacroInvocation mi, Expr e, SideEffect sideEffect, int i, string arg,
70-
string sideEffectDesc
97+
UnsafeMacroInvocation unsafeMacroInvocation, SideEffect sideEffect, int i, string sideEffectDesc
7198
where
72-
not isExcluded(e, SideEffects4Package::sideEffectsInArgumentsToUnsafeMacrosQuery()) and
73-
sideEffect = getASideEffect(e) and
74-
flm.getAnInvocation() = mi and
75-
not exists(mi.getParentInvocation()) and
76-
mi.getAnExpandedElement() = e and
77-
i = flm.getAnUnsafeArgumentIndex() and
78-
arg = mi.getExpandedArgument(i) and
99+
not isExcluded(sideEffect, SideEffects4Package::sideEffectsInArgumentsToUnsafeMacrosQuery()) and
100+
sideEffect = unsafeMacroInvocation.getSideEffectForUnsafeArg(i) and
79101
(
80102
sideEffect instanceof CrementEffect and
81-
exists(arg.indexOf(sideEffect.(CrementOperation).getOperator())) and
82103
sideEffectDesc = "the use of the " + sideEffect.(CrementOperation).getOperator() + " operator"
83104
or
84105
sideEffect instanceof FunctionCallEffect and
85-
exists(arg.indexOf(sideEffect.(FunctionCall).getTarget().getName() + "(")) and
86106
sideEffectDesc =
87107
"a call to the function '" + sideEffect.(FunctionCall).getTarget().getName() + "'"
88108
)
89109
select sideEffect,
90-
"Argument " + mi.getUnexpandedArgument(i) + " to unsafe macro '" + flm.getName() +
91-
"' is expanded to '" + arg + "' multiple times and includes " + sideEffectDesc +
92-
" as a side-effect."
110+
"Argument " + unsafeMacroInvocation.getUnexpandedArgument(i) + " to unsafe macro '" +
111+
unsafeMacroInvocation.getMacroName() + "' is expanded to '" +
112+
unsafeMacroInvocation.getExpandedArgument(i) + "' multiple times and includes " + sideEffectDesc
113+
+ " as a side-effect."

0 commit comments

Comments
 (0)