FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
codeql/cpp/ql/src/Critical/MissingCheckScanf.ql at codeql-cli-2.11.3 · github/codeql · GitHub
github
/
codeql
Public
Notifications
You must be signed in to change notification settings
Fork
2.1k
Star
10.1k
Code
Issues
1k
Pull requests
470
Discussions
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Discussions
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
codeql
/
cpp
/
ql
/
src
/
Critical
/
MissingCheckScanf.ql
Copy path
More file actions
More file actions
Latest commit
History
History
History
122 lines (110 loc) · 3.74 KB
Breadcrumbs
codeql
/
cpp
/
ql
/
src
/
Critical
/
MissingCheckScanf.ql
Copy path
File metadata and controls
122 lines (110 loc) · 3.74 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
/**
* @name Missing return-value check for a 'scanf'-like function
* @description Failing to check that a call to 'scanf' actually writes to an
* output variable can lead to unexpected behavior at reading time.
* @kind problem
* @problem.severity warning
* @security-severity 7.5
* @precision medium
* @id cpp/missing-check-scanf
* @tags security
* correctness
* external/cwe/cwe-252
* external/cwe/cwe-253
*/
import
cpp
import
semmle.code.cpp.commons.Scanf
import
semmle.code.cpp.controlflow.Guards
import
semmle.code.cpp.dataflow.DataFlow
import
semmle.code.cpp.ir.IR
import
semmle.code.cpp.ir.ValueNumbering
/** An expression appearing as an output argument to a `scanf`-like call */
class
ScanfOutput
extends
Expr
{
ScanfFunctionCall
call
;
int
varargIndex
;
Instruction
instr
;
ValueNumber
valNum
;
ScanfOutput
(
)
{
this
=
call
.
getOutputArgument
(
varargIndex
)
.
getFullyConverted
(
)
and
instr
.
getConvertedResultExpression
(
)
=
this
and
valueNumber
(
instr
)
=
valNum
}
ScanfFunctionCall
getCall
(
)
{
result
=
call
}
/**
* Returns the smallest possible `scanf` return value that would indicate
* success in writing this output argument.
*/
int
getMinimumGuardConstant
(
)
{
result
=
varargIndex
+
1
-
count
(
ScanfFormatLiteral
f
,
int
n
|
// Special case: %n writes to an argument without reading any input.
// It does not increase the count returned by `scanf`.
n
<=
varargIndex
and
f
.
getUse
(
)
=
call
and
f
.
getConversionChar
(
n
)
=
"n"
)
}
predicate
hasGuardedAccess
(
Access
e
,
boolean
isGuarded
)
{
e
=
this
.
getAnAccess
(
)
and
if
exists
(
int
value
,
int
minGuard
|
minGuard
=
this
.
getMinimumGuardConstant
(
)
|
e
.
getBasicBlock
(
)
=
blockGuardedBy
(
value
,
"=="
,
call
)
and
minGuard
<=
value
or
e
.
getBasicBlock
(
)
=
blockGuardedBy
(
value
,
"<"
,
call
)
and
minGuard
-
1
<=
value
or
e
.
getBasicBlock
(
)
=
blockGuardedBy
(
value
,
"<="
,
call
)
and
minGuard
<=
value
)
then
isGuarded
=
true
else
isGuarded
=
false
}
/**
* Get a subsequent access of the same underlying storage,
* but before it gets reset or reused in another `scanf` call.
*/
Access
getAnAccess
(
)
{
exists
(
Instruction
dst
|
this
.
bigStep
(
)
=
dst
and
dst
.
getAst
(
)
=
result
and
valueNumber
(
dst
)
=
valNum
)
}
private
Instruction
bigStep
(
)
{
result
=
this
.
smallStep
(
instr
)
or
exists
(
Instruction
i
|
i
=
this
.
bigStep
(
)
|
result
=
this
.
smallStep
(
i
)
)
}
private
Instruction
smallStep
(
Instruction
i
)
{
instr
.
getASuccessor
*
(
)
=
i
and
i
.
getASuccessor
(
)
=
result
and
not
this
.
isBarrier
(
result
)
}
private
predicate
isBarrier
(
Instruction
i
)
{
valueNumber
(
i
)
=
valNum
and
exists
(
Expr
e
|
i
.
getAst
(
)
=
e
|
i
=
any
(
StoreInstruction
s
)
.
getDestinationAddress
(
)
or
[
e
,
e
.
getParent
(
)
.
(
AddressOfExpr
)
]
instanceof
ScanfOutput
)
}
}
/** Returns a block guarded by the assertion of `value op call` */
BasicBlock
blockGuardedBy
(
int
value
,
string
op
,
ScanfFunctionCall
call
)
{
exists
(
GuardCondition
g
,
Expr
left
,
Expr
right
|
right
=
g
.
getAChild
(
)
and
value
=
left
.
getValue
(
)
.
toInt
(
)
and
DataFlow
::
localExprFlow
(
call
,
right
)
|
g
.
ensuresEq
(
left
,
right
,
0
,
result
,
true
)
and
op
=
"=="
or
g
.
ensuresLt
(
left
,
right
,
0
,
result
,
true
)
and
op
=
"<"
or
g
.
ensuresLt
(
left
,
right
,
1
,
result
,
true
)
and
op
=
"<="
)
}
from
ScanfOutput
output
,
ScanfFunctionCall
call
,
Access
access
where
output
.
getCall
(
)
=
call
and
output
.
hasGuardedAccess
(
access
,
false
)
select
access
,
"This variable is read, but may not have been written. "
+
"It should be guarded by a check that the $@ returns at least "
+
output
.
getMinimumGuardConstant
(
)
+
"."
,
call
,
call
.
toString
(
)
Back
|
FazBrowse Home
|
New Git URL