Skip to content

Commit e57e4e1

Browse files
committed
Merge branch 'main' into port-url-redirect-query
2 parents d046e39 + 5db1984 commit e57e4e1

File tree

103 files changed

+9271
-3297
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+9271
-3297
lines changed

cpp/ql/src/semmle/code/cpp/commons/Scanf.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ class Snscanf extends ScanfFunction {
9292
this instanceof TopLevelFunction and
9393
(
9494
hasName("_snscanf") or // _snscanf(src, max_amount, format, args...)
95-
hasName("_snwscanf") // _snwscanf(src, max_amount, format, args...)
95+
hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
96+
hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
97+
hasName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
9698
// note that the max_amount is not a limit on the output length, it's an input length
9799
// limit used with non null-terminated strings.
98100
)
@@ -101,6 +103,12 @@ class Snscanf extends ScanfFunction {
101103
override int getInputParameterIndex() { result = 0 }
102104

103105
override int getFormatParameterIndex() { result = 2 }
106+
107+
/**
108+
* Gets the position at which the maximum number of characters in the
109+
* input string is specified.
110+
*/
111+
int getInputLengthParameterIndex() { result = 1 }
104112
}
105113

106114
/**

cpp/ql/src/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ private import implementations.StdString
2525
private import implementations.Swap
2626
private import implementations.GetDelim
2727
private import implementations.SmartPointer
28+
private import implementations.Sscanf

cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
2424
or
2525
// bcopy(src, dest, num)
2626
// mempcpy(dest, src, num)
27-
this.hasGlobalName(["bcopy", mempcpy(), "__builtin___memcpy_chk"])
27+
// memccpy(dest, src, c, n)
28+
this.hasGlobalName(["bcopy", mempcpy(), "memccpy", "__builtin___memcpy_chk"])
2829
}
2930

3031
/**
@@ -41,7 +42,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
4142
/**
4243
* Gets the index of the parameter that is the size of the copy (in bytes).
4344
*/
44-
int getParamSize() { result = 2 }
45+
int getParamSize() { if this.hasGlobalName("memccpy") then result = 3 else result = 2 }
4546

4647
override predicate hasArrayInput(int bufParam) { bufParam = getParamSrc() }
4748

@@ -71,7 +72,10 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
7172
override predicate hasOnlySpecificWriteSideEffects() { any() }
7273

7374
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
74-
i = getParamDest() and buffer = true and mustWrite = true
75+
i = getParamDest() and
76+
buffer = true and
77+
// memccpy only writes until a given character `c` is found
78+
(if this.hasGlobalName("memccpy") then mustWrite = false else mustWrite = true)
7579
}
7680

7781
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
@@ -97,7 +101,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
97101
}
98102

99103
override predicate parameterIsAlwaysReturned(int index) {
100-
not this.hasGlobalName(["bcopy", mempcpy()]) and
104+
not this.hasGlobalName(["bcopy", mempcpy(), "memccpy"]) and
101105
index = getParamDest()
102106
}
103107
}

cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
1515
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
1616
SideEffectFunction {
1717
MemsetFunction() {
18-
hasGlobalName(["memset", "wmemset", "bzero", "__builtin_memset", "__builtin_memset_chk"]) or
19-
hasQualifiedName("std", ["memset", "wmemset"])
18+
this.hasGlobalOrStdName(["memset", "wmemset"])
19+
or
20+
this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"])
2021
}
2122

2223
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
@@ -28,17 +29,17 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
2829

2930
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
3031
bufParam = 0 and
31-
(if hasGlobalName("bzero") then countParam = 1 else countParam = 2)
32+
(if hasGlobalName(bzero()) then countParam = 1 else countParam = 2)
3233
}
3334

34-
override predicate parameterNeverEscapes(int index) { hasGlobalName("bzero") and index = 0 }
35+
override predicate parameterNeverEscapes(int index) { hasGlobalName(bzero()) and index = 0 }
3536

3637
override predicate parameterEscapesOnlyViaReturn(int index) {
37-
not hasGlobalName("bzero") and index = 0
38+
not hasGlobalName(bzero()) and index = 0
3839
}
3940

4041
override predicate parameterIsAlwaysReturned(int index) {
41-
not hasGlobalName("bzero") and index = 0
42+
not hasGlobalName(bzero()) and index = 0
4243
}
4344

4445
override predicate hasOnlySpecificReadSideEffects() { any() }
@@ -51,6 +52,8 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
5152

5253
override ParameterIndex getParameterSizeIndex(ParameterIndex i) {
5354
i = 0 and
54-
if hasGlobalName("bzero") then result = 1 else result = 2
55+
if hasGlobalName(bzero()) then result = 1 else result = 2
5556
}
5657
}
58+
59+
private string bzero() { result = ["bzero", "explicit_bzero"] }

cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
88
SideEffectFunction {
99
PureStrFunction() {
1010
hasGlobalOrStdName([
11-
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
12-
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
13-
"strtol", "strtoll", "strtoq", "strtoul"
11+
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
12+
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr()
1413
])
1514
}
1615

@@ -24,11 +23,16 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
2423

2524
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
2625
exists(ParameterIndex i |
27-
input.isParameter(i) and
28-
exists(getParameter(i))
29-
or
30-
input.isParameterDeref(i) and
31-
getParameter(i).getUnspecifiedType() instanceof PointerType
26+
(
27+
input.isParameter(i) and
28+
exists(getParameter(i))
29+
or
30+
input.isParameterDeref(i) and
31+
getParameter(i).getUnspecifiedType() instanceof PointerType
32+
) and
33+
// Functions that end with _l also take a locale argument (always as the last argument),
34+
// and we don't want taint from those arguments.
35+
(not this.getName().matches("%\\_l") or exists(getParameter(i + 1)))
3236
) and
3337
(
3438
output.isReturnValueDeref() and
@@ -60,6 +64,31 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
6064
}
6165
}
6266

67+
private string atoi() { result = ["atof", "atoi", "atol", "atoll"] }
68+
69+
private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] }
70+
71+
private string strlwr() {
72+
result = ["_strlwr", "_wcslwr", "_mbslwr", "_strlwr_l", "_wcslwr_l", "_mbslwr_l"]
73+
}
74+
75+
private string strupr() {
76+
result = ["_strupr", "_wcsupr", "_mbsupr", "_strupr_l", "_wcsupr_l", "_mbsupr_l"]
77+
}
78+
79+
private string strrev() { result = ["_strrev", "_wcsrev", "_mbsrev", "_mbsrev_l"] }
80+
81+
private string strcmp() {
82+
// NOTE: `strcoll` doesn't satisfy _all_ the definitions of purity: its behavior depends on
83+
// `LC_COLLATE` (which is set by `setlocale`). Not sure this behavior worth including in the model, so
84+
// for now we interpret the function as being pure.
85+
result =
86+
[
87+
"strcmp", "strcspn", "strncmp", "strcoll", "strverscmp", "_mbsnbcmp", "_mbsnbcmp_l",
88+
"_stricmp"
89+
]
90+
}
91+
6392
/** String standard `strlen` function, and related functions for computing string lengths. */
6493
private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction {
6594
StrLenFunction() {
@@ -114,19 +143,28 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
114143
/** Pure raw-memory functions. */
115144
private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
116145
SideEffectFunction {
117-
PureMemFunction() { hasGlobalOrStdName(["memchr", "memrchr", "rawmemchr", "memcmp", "memmem"]) }
146+
PureMemFunction() {
147+
hasGlobalOrStdName([
148+
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"
149+
]) or
150+
this.hasGlobalName("memfrob")
151+
}
118152

119153
override predicate hasArrayInput(int bufParam) {
120154
getParameter(bufParam).getUnspecifiedType() instanceof PointerType
121155
}
122156

123157
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
124158
exists(ParameterIndex i |
125-
input.isParameter(i) and
126-
exists(getParameter(i))
127-
or
128-
input.isParameterDeref(i) and
129-
getParameter(i).getUnspecifiedType() instanceof PointerType
159+
(
160+
input.isParameter(i) and
161+
exists(getParameter(i))
162+
or
163+
input.isParameterDeref(i) and
164+
getParameter(i).getUnspecifiedType() instanceof PointerType
165+
) and
166+
// `memfrob` should not have taint from the size argument.
167+
(not this.hasGlobalName("memfrob") or i = 0)
130168
) and
131169
(
132170
output.isReturnValueDeref() and
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Provides implementation classes modeling `sscanf`, `fscanf` and various similar
3+
* functions. See `semmle.code.cpp.models.Models` for usage information.
4+
*/
5+
6+
import semmle.code.cpp.Function
7+
import semmle.code.cpp.commons.Scanf
8+
import semmle.code.cpp.models.interfaces.ArrayFunction
9+
import semmle.code.cpp.models.interfaces.Taint
10+
import semmle.code.cpp.models.interfaces.Alias
11+
import semmle.code.cpp.models.interfaces.SideEffect
12+
13+
/**
14+
* The standard function `sscanf`, `fscanf` and its assorted variants
15+
*/
16+
private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, SideEffectFunction {
17+
SscanfModel() { this instanceof Sscanf or this instanceof Fscanf or this instanceof Snscanf }
18+
19+
override predicate hasArrayWithNullTerminator(int bufParam) {
20+
bufParam = this.(ScanfFunction).getFormatParameterIndex()
21+
or
22+
not this instanceof Fscanf and
23+
bufParam = this.(ScanfFunction).getInputParameterIndex()
24+
}
25+
26+
override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) }
27+
28+
private int getLengthParameterIndex() { result = this.(Snscanf).getInputLengthParameterIndex() }
29+
30+
private int getLocaleParameterIndex() {
31+
this.getName().matches("%\\_l") and
32+
(
33+
if exists(getLengthParameterIndex())
34+
then result = getLengthParameterIndex() + 2
35+
else result = 2
36+
)
37+
}
38+
39+
private int getArgsStartPosition() { result = this.getNumberOfParameters() }
40+
41+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
42+
input.isParameterDeref(this.(ScanfFunction).getInputParameterIndex()) and
43+
output.isParameterDeref(any(int i | i >= getArgsStartPosition()))
44+
}
45+
46+
override predicate parameterNeverEscapes(int index) {
47+
index = [0 .. max(getACallToThisFunction().getNumberOfArguments())]
48+
}
49+
50+
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
51+
52+
override predicate parameterIsAlwaysReturned(int index) { none() }
53+
54+
override predicate hasOnlySpecificReadSideEffects() { any() }
55+
56+
override predicate hasOnlySpecificWriteSideEffects() { any() }
57+
58+
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
59+
i >= getArgsStartPosition() and
60+
buffer = true and
61+
mustWrite = true
62+
}
63+
64+
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
65+
buffer = true and
66+
i =
67+
[
68+
this.(ScanfFunction).getInputParameterIndex(),
69+
this.(ScanfFunction).getFormatParameterIndex(), getLocaleParameterIndex()
70+
]
71+
}
72+
}

cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,20 @@ import semmle.code.cpp.models.interfaces.SideEffect
1313
*/
1414
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
1515
StrcatFunction() {
16-
getName() =
17-
[
16+
this.hasGlobalOrStdName([
1817
"strcat", // strcat(dst, src)
1918
"strncat", // strncat(dst, src, max_amount)
2019
"wcscat", // wcscat(dst, src)
20+
"wcsncat" // wcsncat(dst, src, max_amount)
21+
])
22+
or
23+
this.hasGlobalName([
2124
"_mbscat", // _mbscat(dst, src)
22-
"wcsncat", // wcsncat(dst, src, max_amount)
2325
"_mbsncat", // _mbsncat(dst, src, max_amount)
24-
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
25-
]
26+
"_mbsncat_l", // _mbsncat_l(dst, src, max_amount, locale)
27+
"_mbsnbcat", // _mbsnbcat(dest, src, count)
28+
"_mbsnbcat_l" // _mbsnbcat_l(dest, src, count, locale)
29+
])
2630
}
2731

2832
/**
@@ -50,7 +54,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
5054
input.isParameter(2) and
5155
output.isParameterDeref(0)
5256
or
53-
getName() = "_mbsncat_l" and
57+
getName() = ["_mbsncat_l", "_mbsnbcat_l"] and
5458
input.isParameter(3) and
5559
output.isParameterDeref(0)
5660
or

cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,36 @@ import semmle.code.cpp.models.interfaces.SideEffect
1313
*/
1414
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
1515
StrcpyFunction() {
16-
getName() =
17-
[
16+
this.hasGlobalOrStdName([
1817
"strcpy", // strcpy(dst, src)
1918
"wcscpy", // wcscpy(dst, src)
20-
"_mbscpy", // _mbscpy(dst, src)
2119
"strncpy", // strncpy(dst, src, max_amount)
22-
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
2320
"wcsncpy", // wcsncpy(dst, src, max_amount)
21+
"strxfrm", // strxfrm(dest, src, max_amount)
22+
"wcsxfrm" // wcsxfrm(dest, src, max_amount)
23+
])
24+
or
25+
this.hasGlobalName([
26+
"_mbscpy", // _mbscpy(dst, src)
27+
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
2428
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
2529
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
26-
"_mbsncpy_l"
27-
] // _mbsncpy_l(dst, src, max_amount, locale)
30+
"_mbsncpy_l", // _mbsncpy_l(dst, src, max_amount, locale)
31+
"_strxfrm_l", // _strxfrm_l(dest, src, max_amount, locale)
32+
"wcsxfrm_l", // _strxfrm_l(dest, src, max_amount, locale)
33+
"_mbsnbcpy", // _mbsnbcpy(dest, src, max_amount)
34+
"stpcpy", // stpcpy(dest, src)
35+
"stpncpy" // stpcpy(dest, src, max_amount)
36+
])
2837
or
29-
getName() =
30-
[
31-
"strcpy_s", // strcpy_s(dst, max_amount, src)
32-
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
33-
"_mbscpy_s"
34-
] and // _mbscpy_s(dst, max_amount, src)
38+
(
39+
this.hasGlobalOrStdName([
40+
"strcpy_s", // strcpy_s(dst, max_amount, src)
41+
"wcscpy_s" // wcscpy_s(dst, max_amount, src)
42+
])
43+
or
44+
this.hasGlobalName("_mbscpy_s") // _mbscpy_s(dst, max_amount, src)
45+
) and
3546
// exclude the 2-parameter template versions
3647
// that find the size of a fixed size destination buffer.
3748
getNumberOfParameters() = 3
@@ -48,10 +59,10 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
4859
int getParamSize() {
4960
if isSVariant()
5061
then result = 1
51-
else
52-
if exists(getName().indexOf("ncpy"))
53-
then result = 2
54-
else none()
62+
else (
63+
getName().matches(["%ncpy%", "%nbcpy%", "%xfrm%"]) and
64+
result = 2
65+
)
5566
}
5667

5768
/**

0 commit comments

Comments
 (0)