-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathDoNotModifyConstantObjects.ql
61 lines (54 loc) · 1.72 KB
/
DoNotModifyConstantObjects.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
/**
* @id c/cert/do-not-modify-constant-objects
* @name EXP40-C: Do not modify constant objects
* @description Do not modify constant objects. This may result in undefined behavior.
* @kind path-problem
* @precision high
* @problem.severity error
* @tags external/cert/id/exp40-c
* correctness
* external/cert/obligation/rule
*/
import cpp
import codingstandards.c.cert
import semmle.code.cpp.dataflow.new.DataFlow
import CastFlow::PathGraph
import codingstandards.cpp.SideEffect
class ConstRemovingCast extends Cast {
ConstRemovingCast() {
this.getExpr().getType().(DerivedType).getBaseType*().isConst() and
not this.getType().(DerivedType).getBaseType*().isConst()
}
}
class MaybeReturnsStringLiteralFunctionCall extends FunctionCall {
MaybeReturnsStringLiteralFunctionCall() {
getTarget().getName() in [
"strpbrk", "strchr", "strrchr", "strstr", "wcspbrk", "wcschr", "wcsrchr", "wcsstr",
"memchr", "wmemchr"
]
}
}
module CastConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().getFullyConverted() instanceof ConstRemovingCast
or
source.asExpr().getFullyConverted() = any(MaybeReturnsStringLiteralFunctionCall c)
}
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(Assignment a).getLValue().(PointerDereferenceExpr).getOperand()
}
}
module CastFlow = DataFlow::Global<CastConfig>;
from CastFlow::PathNode src, CastFlow::PathNode sink
where
CastFlow::flowPath(src, sink)
or
sink.getNode()
.asExpr()
.(VariableEffect)
.getTarget()
.getType()
.(DerivedType)
.getBaseType*()
.isConst()
select sink, src, sink, "Const variable assigned with non const-value."