Skip to content

Commit bddb5fd

Browse files
authored
Add files via upload
1 parent 3d1f4d5 commit bddb5fd

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
...
2+
r = scanf("%i", i);
3+
if (r == 1) // GOOD
4+
return i;
5+
else
6+
return -1;
7+
...
8+
scanf("%i", i); // BAD
9+
return i;
10+
...
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Working with reading data without validation procedures and with uninitialized arguments can lead to unpredictable consequences.</p>
7+
8+
</recommendation>
9+
<example>
10+
<p>The following example demonstrates erroneous and corrected work with a function call.</p>
11+
<sample src="ImproperCheckReturnValueScanf.cpp" />
12+
13+
</example>
14+
<references>
15+
16+
<li>
17+
CERT C Coding Standard:
18+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP12-C.+Do+not+ignore+values+returned+by+functions">EXP12-C. Do not ignore values returned by functions</a>.
19+
</li>
20+
21+
</references>
22+
</qhelp>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* @name Improper check return value scanf.
3+
* @description Using a function call without the ability to evaluate the correctness of the work can lead to unexpected results.
4+
* @kind problem
5+
* @id cpp/improper-check-return-value-scanf
6+
* @problem.severity warning
7+
* @precision medium
8+
* @tags correctness
9+
* security
10+
* external/cwe/cwe-754
11+
* external/cwe/cwe-908
12+
*/
13+
14+
import cpp
15+
import semmle.code.cpp.commons.Exclusions
16+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
17+
18+
/** Returns the starting position of the argument being filled. */
19+
int posArgumentInFunctionCall(FunctionCall fc) {
20+
(
21+
(
22+
fc.getTarget().hasGlobalOrStdName("scanf") or
23+
fc.getTarget().hasGlobalOrStdName("scanf_s")
24+
) and
25+
result = 1
26+
or
27+
(
28+
fc.getTarget().hasGlobalOrStdName("fscanf") or
29+
fc.getTarget().hasGlobalOrStdName("sscanf") or
30+
fc.getTarget().hasGlobalOrStdName("fscanf_s") or
31+
fc.getTarget().hasGlobalOrStdName("sscanf_s")
32+
) and
33+
result = 2
34+
)
35+
}
36+
37+
from FunctionCall fc, int n
38+
where
39+
n = posArgumentInFunctionCall(fc) and
40+
// Function return value is not evaluated.
41+
fc instanceof ExprInVoidContext and
42+
not isFromMacroDefinition(fc) and
43+
exists(Expr e0, int i |
44+
i in [n .. fc.getNumberOfArguments() - 1] and
45+
// Fillable argument was not initialized.
46+
(
47+
fc.getArgument(i).(VariableAccess).getTarget() instanceof LocalScopeVariable or
48+
fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() instanceof
49+
LocalScopeVariable
50+
) and
51+
(
52+
not fc.getArgument(i).(VariableAccess).getTarget().hasInitializer() and
53+
not fc.getArgument(i)
54+
.(AddressOfExpr)
55+
.getOperand()
56+
.(VariableAccess)
57+
.getTarget()
58+
.hasInitializer()
59+
) and
60+
(
61+
not fc.getArgument(i).(VariableAccess).getTarget().getAnAssignment().getASuccessor+() = fc and
62+
not fc.getArgument(i)
63+
.(AddressOfExpr)
64+
.getOperand()
65+
.(VariableAccess)
66+
.getTarget()
67+
.getAnAssignment()
68+
.getASuccessor+() = fc
69+
) and
70+
// After the call, the completed arguments are assigned or returned as the result of the operation of the upper function.
71+
fc.getASuccessor+() = e0 and
72+
(
73+
(
74+
e0.(Assignment).getRValue().(VariableAccess).getTarget() =
75+
fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or
76+
e0.(Assignment).getRValue().(VariableAccess).getTarget() =
77+
fc.getArgument(i).(VariableAccess).getTarget()
78+
)
79+
or
80+
e0.getEnclosingStmt() instanceof ReturnStmt and
81+
(
82+
e0.(VariableAccess).getTarget() =
83+
fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or
84+
e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget()
85+
)
86+
or
87+
not exists(Expr e1 |
88+
fc.getASuccessor+() = e1 and
89+
(
90+
e1.(VariableAccess).getTarget() =
91+
fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget() or
92+
e1.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget()
93+
)
94+
)
95+
)
96+
) and
97+
// After the call, filled arguments are not evaluated.
98+
not exists(Expr e0, int i |
99+
i in [n .. fc.getNumberOfArguments() - 1] and
100+
fc.getASuccessor+() = e0 and
101+
e0.getEnclosingElement() instanceof ComparisonOperation and
102+
(
103+
e0.(VariableAccess).getTarget() = fc.getArgument(i).(VariableAccess).getTarget() or
104+
e0.(VariableAccess).getTarget() =
105+
fc.getArgument(i).(AddressOfExpr).getOperand().(VariableAccess).getTarget()
106+
)
107+
)
108+
select fc, "Unchecked return value for call to '" + fc.getTarget().getName() + "'."

0 commit comments

Comments
 (0)