- Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathUnterminatedVarargsCall.ql
81 lines (70 loc) · 2.67 KB
/
UnterminatedVarargsCall.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
/**
* @name Unterminated variadic call
* @description Calling a variadic function without a sentinel value
* may result in a buffer overflow if the function expects
* a specific value to terminate the argument list.
* @kind problem
* @problem.severity warning
* @security-severity 8.8
* @precision medium
* @id cpp/unterminated-variadic-call
* @tags reliability
* security
* external/cwe/cwe-121
*/
import cpp
/**
* Gets a normalized textual representation of `e`'s value.
* The result is the same as `Expr.getValue()`, except if there is a
* trailing `".0"` then it is removed. This means that, for example,
* the values of `-1` and `-1.0` would be considered the same.
*/
stringnormalisedExprValue(Expre){result=e.getValue().regexpReplaceAll("\\.0$","")}
/**
* A variadic function which is not a formatting function.
*/
classVarargsFunctionextendsFunction{
VarargsFunction(){
this.isVarargs()and
notthisinstanceofFormattingFunction
}
ExprtrailingArgumentIn(FunctionCallfc){
fc=this.getACallToThisFunction()and
result=fc.getArgument(fc.getNumberOfArguments()-1)
}
stringtrailingArgValue(FunctionCallfc){
result=normalisedExprValue(this.trailingArgumentIn(fc))
}
privateinttrailingArgValueCount(stringvalue){
result=strictcount(FunctionCallfc|this.trailingArgValue(fc)=value)
}
stringnonTrailingVarArgValue(FunctionCallfc,intindex){
fc=this.getACallToThisFunction()and
index>=this.getNumberOfParameters()and
index<fc.getNumberOfArguments()-1and
result=normalisedExprValue(fc.getArgument(index))
}
privateinttotalCount(){
result=strictcount(FunctionCallfc|fc=this.getACallToThisFunction())
}
stringnormalTerminator(intcnt,inttotalCount){
// the terminator is 0 or -1
result=["0","-1"]and
// at least 80% of calls have the terminator
cnt=this.trailingArgValueCount(result)and
totalCount=this.totalCount()and
100*cnt/totalCount>=80and
// terminator value is not used in a non-terminating position
notthis.nonTrailingVarArgValue(_, _)=result
}
predicateisWhitelisted(){this.hasGlobalName(["open","fcntl","ptrace","mremap"])}
}
fromVarargsFunctionf,FunctionCallfc,stringterminator,intcnt,inttotalCount
where
terminator=f.normalTerminator(cnt,totalCount)and
fc=f.getACallToThisFunction()and
notnormalisedExprValue(f.trailingArgumentIn(fc))=terminatorand
notf.isWhitelisted()
selectfc,
"Calls to $@ should use the value "+terminator+" as a terminator ("+cnt+" of "+
totalCount+" calls do).",f,f.getQualifiedName()