Skip to content

Commit 0f5a4a7

Browse files
committed
[CPP-370] Improve handling of _ macros by using taint sanitizers.
1 parent 8f79cdb commit 0f5a4a7

File tree

4 files changed

+22
-16
lines changed

4 files changed

+22
-16
lines changed

cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,22 @@ predicate whitelistFunction(Function f, int arg) {
4242
(arg = 1 or arg = 2)
4343
}
4444

45-
predicate whitelisted(FunctionCall fc) {
46-
exists(Function f, int arg | f = fc.getTarget() | whitelistFunction(f, arg))
45+
// we assume that ALL uses of the `_` macro
46+
// return constant string literals
47+
predicate underscoreMacro(Expr e) {
48+
exists(MacroInvocation mi |
49+
mi.getMacroName() = "_" and
50+
mi.getExpr() = e
51+
)
4752
}
4853

4954
predicate isNonConst(DataFlow::Node node) {
5055
exists(Expr e | e = node.asExpr() |
5156
exists(FunctionCall fc | fc = e.(FunctionCall) |
52-
not whitelisted(fc) and not fc.getTarget().hasDefinition()
57+
not (
58+
whitelistFunction(fc.getTarget(), _) or
59+
fc.getTarget().hasDefinition()
60+
)
5361
)
5462
or
5563
exists(Parameter p | p = e.(VariableAccess).getTarget().(Parameter) |
@@ -97,10 +105,10 @@ class NonConstFlow extends TaintTracking::Configuration {
97105
override predicate isSource(DataFlow::Node source) { isNonConst(source) }
98106

99107
override predicate isSink(DataFlow::Node sink) {
100-
exists(FormattingFunctionCall fc |
101-
sink.asExpr() = fc.getArgument(fc.getFormatParameterIndex())
102-
)
108+
exists(FormattingFunctionCall fc | sink.asExpr() = fc.getArgument(fc.getFormatParameterIndex()))
103109
}
110+
111+
override predicate isSanitizer(DataFlow::Node node) { underscoreMacro(node.asExpr()) }
104112
}
105113

106114
from FormattingFunctionCall call, Expr formatString

cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int main(int argc, char **argv) {
3131
else
3232
printf("No argument supplied.\n"); // ok
3333

34-
printf(_("No argument supplied.\n")); // not ok
34+
printf(_("No argument supplied.\n")); // ok
3535

3636
printf(dgettext(NULL, "No argument supplied.\n")); // ok
3737

@@ -40,10 +40,10 @@ int main(int argc, char **argv) {
4040
printf(gettext("%d arguments\n"), argc-1); // ok
4141
printf(any_random_function("%d arguments\n"), argc-1); // not ok
4242

43-
// Since `_` is mapped to `some_random_function` above,
44-
// the following call will be flagged.
43+
// Even though `_` is mapped to `some_random_function` above,
44+
// the following call should not be flagged.
4545
printf(_(any_random_function("%d arguments\n")),
46-
argc-1); // not ok
46+
argc-1); // ok
4747

4848
return 0;
4949
}

cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
| NonConstantFormat.c:30:10:30:16 | access to array | The format string argument to printf should be constant to prevent security issues and other potential errors. |
2-
| NonConstantFormat.c:34:9:34:36 | call to any_random_function | The format string argument to printf should be constant to prevent security issues and other potential errors. |
32
| NonConstantFormat.c:41:9:41:27 | call to any_random_function | The format string argument to printf should be constant to prevent security issues and other potential errors. |
4-
| NonConstantFormat.c:45:9:45:48 | call to any_random_function | The format string argument to printf should be constant to prevent security issues and other potential errors. |
53
| nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. |
64
| nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
75
| nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |

cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/nested.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extern "C" int snprintf ( char * s, int n, const char * format, ... );
1818
struct A {
1919
void do_print(const char *fmt0) {
2020
char buf[32];
21-
snprintf(buf, 32, fmt0); // GOOD
21+
snprintf(buf, 32, fmt0); // BAD [FALSE POSITIVE]
2222
}
2323
};
2424

@@ -39,7 +39,7 @@ struct C {
3939

4040
void foo(void) {
4141
C c;
42-
c.do_some_printing(c.ext_fmt_str());
42+
c.do_some_printing(c.ext_fmt_str()); // GOOD [NOT DETECTED]
4343
}
4444

4545
struct some_class {
@@ -76,15 +76,15 @@ void diagnostic(const char *fmt, ...)
7676
}
7777

7878
void bar(void) {
79-
diagnostic (some_instance->get_fmt()); // GOOD
79+
diagnostic (some_instance->get_fmt()); // BAD
8080
}
8181

8282
namespace ns {
8383

8484
class blab {
8585
void out1(void) {
8686
char *fmt = (char *)__builtin_alloca(10);
87-
diagnostic(fmt); // GOOD
87+
diagnostic(fmt); // BAD
8888
}
8989
};
9090
}

0 commit comments

Comments
 (0)