Skip to content
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

C++: Improvements to reduce false alarms #16149

Merged
merged 10 commits into from
Apr 16, 2024
12 changes: 10 additions & 2 deletions cpp/ql/src/Critical/GlobalUseBeforeInit.ql
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ predicate useFunc(GlobalVariable v, Function f) {
}

predicate uninitialisedBefore(GlobalVariable v, Function f) {
f.hasGlobalName("main")
f.hasGlobalName("main") and
not initialisedAtDeclaration(v) and
not isStdlibVariable(v)
or
exists(Call call, Function g |
uninitialisedBefore(v, g) and
Expand Down Expand Up @@ -98,10 +100,16 @@ predicate callReaches(Call call, ControlFlowNode successor) {
)
}

/** Holds if `v` has an initializer. */
predicate initialisedAtDeclaration(GlobalVariable v) { exists(v.getInitializer()) }

/** Holds if `v` is a global variable that does not need to be initialized. */
predicate isStdlibVariable(GlobalVariable v) { v.hasGlobalName(["stdin", "stdout", "stderr"]) }

from GlobalVariable v, Function f
where
uninitialisedBefore(v, f) and
useFunc(v, f)
select f,
"The variable '" + v.getName() +
"The variable '" + v.getName() + "'" +
" is used in this function but may not be initialized when it is called."
2 changes: 2 additions & 0 deletions cpp/ql/src/Critical/InconsistentNullnessTesting.ql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import cpp
from StackVariable v, ControlFlowNode def, VariableAccess checked, VariableAccess unchecked
where
checked = v.getAnAccess() and
// The check can often be in a macro for handling exception
not checked.isInMacroExpansion() and
dereferenced(checked) and
unchecked = v.getAnAccess() and
dereferenced(unchecked) and
Expand Down
5 changes: 5 additions & 0 deletions cpp/ql/src/change-notes/2024-04-09-reduce-FP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The "Global variable may be used before initialization" query (`cpp/global-use-before-init`) no longer raises an alert on global variables that are initialized when they are declared.
* The "Inconsistent null check of pointer" query (`cpp/inconsistent-nullness-testing`) query no longer raises an alert when the guarded check is in a macro expansion.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.cpp:27:5:27:6 | f1 | The variable 'b' is used in this function but may not be initialized when it is called. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Critical/GlobalUseBeforeInit.ql
38 changes: 38 additions & 0 deletions cpp/ql/test/query-tests/Critical/GlobalUseBeforeInit/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
typedef __builtin_va_list va_list;
typedef struct {} FILE;

extern FILE * stdin;
extern FILE * stdout;
extern FILE * stderr;

#define va_start(args, fmt) __builtin_va_start(args,fmt)
#define va_end(args) __builtin_va_end(args);

int vfprintf (FILE *, const char *, va_list);

int a = 1;
int b;

int my_printf(const char * fmt, ...)
{
va_list vl;
int ret;
va_start(vl, fmt);
ret = vfprintf(stdout, fmt, vl);
ret = vfprintf(stderr, fmt, vl);
va_end(vl);
return ret;
}

int f1()
{
my_printf("%d\n", a + 2);
my_printf("%d\n", b + 2); // BAD
return 0;
}

int main()
{
int b = f1();
return 0;
}
Loading