-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscanf_checker.cpp
64 lines (56 loc) · 1.64 KB
/
scanf_checker.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// clang-format off
// order of #includes matters
#include <gcc-plugin.h>
#include <tree.h>
#include <plugin-version.h>
#include <gimple.h>
#include <gimple-iterator.h>
#include <diagnostic.h>
// clang-format on
#include <assert.h>
int plugin_is_GPL_compatible;
static const char *get_string_from_tree(tree tr) {
switch (TREE_CODE(tr)) {
case STRING_CST:
return TREE_STRING_POINTER(tr);
case ADDR_EXPR:
return get_string_from_tree(TREE_OPERAND(tr, 0));
case SSA_NAME: {
gimple *def_stmt = SSA_NAME_DEF_STMT(tr);
assert(def_stmt && gimple_assign_single_p(def_stmt));
return get_string_from_tree(gimple_assign_rhs1(def_stmt));
}
default:
return nullptr;
}
}
static void plugin_callback(void *, void *) {
basic_block bb;
FOR_EACH_BB_FN(bb, cfun) {
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
gimple *stmt = gsi_stmt(gsi);
if (!is_gimple_call(stmt))
continue;
tree fn_decl = gimple_call_fndecl(stmt);
if (fn_decl == NULL_TREE)
continue;
if (TREE_CODE(fn_decl) != FUNCTION_DECL)
continue;
if (!strcmp(IDENTIFIER_POINTER(DECL_NAME(fn_decl)), "scanf")) {
const char *fmt = get_string_from_tree(gimple_call_arg(stmt, 0));
if (fmt && strstr(fmt, "%s")) {
warning_at(gimple_location(stmt), OPT_fplugin_,
"format string contains insecure %%s specifier");
}
}
}
}
}
int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version)) {
return 1;
}
register_callback(plugin_info->base_name, PLUGIN_ALL_PASSES_START, plugin_callback, NULL);
return 0;
}