-
Notifications
You must be signed in to change notification settings - Fork 0
/
argv-out-of-bounds-0.ql
137 lines (129 loc) · 4.99 KB
/
argv-out-of-bounds-0.ql
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* @name Argv index out-of-bounds-0
* @kind problem
* @id cpp/example/argv-out-of-bounds-0
*/
import cpp
/*
* This query's goal is to isolate the parts of the source relevant to the bug, namely
* declaration | 435 main (int argc, char *argv[])
* | 436 {
* | ...
* init other var; | 534 for (n = 1;
* compare to argc | n < (guint) argc;
* update other var | n++)
* | 535 {
* | ...
* | 568 }
* | ...
* indexed read | 610 path = g_strdup (argv[n]);
* | ...
* | 629 if (path[0] != '/')
* | 630 {
* | ...
* | 632 s = g_find_program_in_path (path);
* | ...
* indexed write | 639 argv[n] = path = s;
* | 640 }
*
* As reference, use
* https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-cpp/
* to find the codeql class matching c++ syntax
*/
/* Too many results */
// from Parameter argc
// where argc.getName() = "argc"
// select argc, "Definition of argc"
//
/*
* Include the comparison operation to narrow results.
* Still finds 12 results.
*/
// from Parameter argc, ComparisonOperation cmp
// where
// argc.getName() = "argc" and
// argc.getAnAccess() = cmp.getAnOperand().getAChild*()
// select argc, "Definition of argc", cmp, "use in comparison"
/*
* Make sure there is another variable in the comparison. Refer to it as `n`
* Note that a ql `Parameter` is also a `Variable`, so we look for non-parameters.
* This narrows the `alerts` to 2 results, but still leaves 8 `#select`s
*/
// from Parameter argc, ComparisonOperation cmp, Variable n
// where
// argc.getName() = "argc" and
// argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
// n.getAnAccess() = cmp.getAnOperand().getAChild*() and
// not n instanceof Parameter
// select argc, "definition of argc", cmp, "use in comparison", n, "other var in comparison"
/*
* Find `n`'s use as argv index. This still results in two alerts (which are grouped
* by definitions of `argc`), and actually increases the `#select`s.
*/
// from Parameter argc, ComparisonOperation cmp, Variable n, Parameter argv, ArrayExpr argvAccess
// where
// argc.getName() = "argc" and
// argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
// n.getAnAccess() = cmp.getAnOperand().getAChild*() and
// not n instanceof Parameter and
// argvAccess.getArrayBase() = argv.getAnAccess() and
// argvAccess.getArrayOffset() = n.getAnAccess()
// select argc, "definition of argc", cmp, "use in comparison", n, "other var in comparison",
// argvAccess, "argv indexed"
/*
* Narrow further by requiring writes involving `argv[n]`.
*
* This finally narrows results to a single function and 14 `#select`s;
* until now there was a chance we might find variants of the same problem,
* but now it looks like there aren't any.
*
* Examining the `argvAccess` column, it's clear that most reads we don't
* care about are in the form of `strcmp (argv[n], ...)`
*/
// from
// Parameter argc, ComparisonOperation cmp, Variable n, Parameter argv, ArrayExpr argvAccess,
// AssignExpr argvSet
// where
// argc.getName() = "argc" and
// argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
// n.getAnAccess() = cmp.getAnOperand().getAChild*() and
// not n instanceof Parameter and
// argvAccess.getArrayBase() = argv.getAnAccess() and
// argvAccess.getArrayOffset() = n.getAnAccess() and
// exists(ArrayExpr aa |
// aa.getArrayBase() = argv.getAnAccess() and
// aa.getArrayOffset() = n.getAnAccess() and
// argvSet.getLValue() = aa and
// /* Separate the read */
// aa != argvAccess
// )
// select argc, "definition of argc", cmp, "use in comparison", n, "other var in comparison",
// argvAccess, "argv indexed", argvSet, "argv assigned"
/*
* Filter out the `strcmp(argv[n],...) expressions.
*
* This only returns 4 results, specific enough for some range analysis work.
*/
from
Parameter argc, ComparisonOperation cmp, Variable n, Parameter argv, ArrayExpr argvAccess,
AssignExpr argvSet
where
argc.getName() = "argc" and
argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
n.getAnAccess() = cmp.getAnOperand().getAChild*() and
not n instanceof Parameter and
argvAccess.getArrayBase() = argv.getAnAccess() and
argvAccess.getArrayOffset() = n.getAnAccess() and
not exists(FunctionCall strcmp |
strcmp.getTarget().getName() = "strcmp" and
strcmp.getAnArgument*() = argvAccess
) and
exists(ArrayExpr aa |
aa.getArrayBase() = argv.getAnAccess() and
aa.getArrayOffset() = n.getAnAccess() and
argvSet.getLValue() = aa and
/* Separate the read */
aa != argvAccess
)
select argc, "definition of argc", cmp, "use in comparison", n, "other var in comparison",
argvAccess, "argv indexed", argvSet, "argv assigned"