mirror of
https://github.com/github/codeql.git
synced 2026-05-17 20:57:07 +02:00
Compare commits
361 Commits
codeql-cli
...
remove-jav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee314a4dad | ||
|
|
8dcf7926de | ||
|
|
d09c3bf863 | ||
|
|
1a92fa5d92 | ||
|
|
8d2ad4ed17 | ||
|
|
5f659f6e48 | ||
|
|
ee46717c76 | ||
|
|
914e621d1b | ||
|
|
976190e84d | ||
|
|
06eb93da3f | ||
|
|
7197f41e75 | ||
|
|
5488872044 | ||
|
|
413ac4e8f4 | ||
|
|
cec6cd0830 | ||
|
|
39a12a8464 | ||
|
|
46eb27cd01 | ||
|
|
ba98c0c1cb | ||
|
|
fc8b439263 | ||
|
|
a358ea8667 | ||
|
|
c294b75f6c | ||
|
|
d5e17f9ebf | ||
|
|
c7ea7ca5cd | ||
|
|
49c656d904 | ||
|
|
79549c2285 | ||
|
|
787f36f056 | ||
|
|
b7b229d59b | ||
|
|
64fcbe05c3 | ||
|
|
31c34870ef | ||
|
|
3c17ac424d | ||
|
|
bb6c079e5a | ||
|
|
a3c1975a84 | ||
|
|
bdd78d2bc7 | ||
|
|
29db42c3cd | ||
|
|
e6df8164cf | ||
|
|
cf03bd8bd1 | ||
|
|
342c14887b | ||
|
|
e1101e582e | ||
|
|
768203bd36 | ||
|
|
c51fb00082 | ||
|
|
0a92b04c8b | ||
|
|
15161d8867 | ||
|
|
53ee465726 | ||
|
|
a20acfee25 | ||
|
|
f69787afd0 | ||
|
|
9b12980688 | ||
|
|
cb0f82c36e | ||
|
|
3b678bfbc5 | ||
|
|
e1750adc38 | ||
|
|
fd0fb9483e | ||
|
|
3d1d491e6b | ||
|
|
18020707b8 | ||
|
|
cfa0d46b73 | ||
|
|
e027d514f1 | ||
|
|
d5f675c2dc | ||
|
|
78c12dc505 | ||
|
|
ad08ccb50b | ||
|
|
95751fcc21 | ||
|
|
13417dbf14 | ||
|
|
ff21662b23 | ||
|
|
6967b06dee | ||
|
|
fc58ada92e | ||
|
|
108118afa3 | ||
|
|
d8bb5273e7 | ||
|
|
c792567904 | ||
|
|
6d9a88d1c8 | ||
|
|
3520fed752 | ||
|
|
d10dbbdd9d | ||
|
|
6bf1e87bbe | ||
|
|
91f46624b6 | ||
|
|
94f32d2985 | ||
|
|
569426b04e | ||
|
|
b0852f6c16 | ||
|
|
b985ddb868 | ||
|
|
079769ed2e | ||
|
|
fc6af0476f | ||
|
|
03bd7d7f96 | ||
|
|
92ffd8c465 | ||
|
|
b0836a620c | ||
|
|
06b36f742e | ||
|
|
c977cfe40a | ||
|
|
e0921ac983 | ||
|
|
7e7dfe2cc4 | ||
|
|
91a8b9fdd9 | ||
|
|
8debae1a3b | ||
|
|
547cbb6322 | ||
|
|
1adc5c2a5b | ||
|
|
d39df18544 | ||
|
|
e664711f47 | ||
|
|
7d3a219f63 | ||
|
|
23e4ad1abb | ||
|
|
3e1bc66984 | ||
|
|
26d2fbd217 | ||
|
|
913a679ef5 | ||
|
|
aebde189f8 | ||
|
|
66c206cc61 | ||
|
|
c9640ffdbc | ||
|
|
24214002a1 | ||
|
|
eba1b0bc15 | ||
|
|
289660067c | ||
|
|
854f2a046a | ||
|
|
69541d3628 | ||
|
|
70e1724463 | ||
|
|
cbdabe35de | ||
|
|
c9c41252e3 | ||
|
|
3437cf2909 | ||
|
|
d7afd86a27 | ||
|
|
38ca5aba98 | ||
|
|
4e6a8d991e | ||
|
|
cb0a567c03 | ||
|
|
032ac50034 | ||
|
|
3e5f7d0db5 | ||
|
|
b08eabec68 | ||
|
|
a4a9e2aa96 | ||
|
|
3189c578a4 | ||
|
|
c2b356ab08 | ||
|
|
ceb9a0bd6b | ||
|
|
a031b2a090 | ||
|
|
b52a2cd292 | ||
|
|
6be4b3bac6 | ||
|
|
4841c3037d | ||
|
|
f14e3f6007 | ||
|
|
83fb41e414 | ||
|
|
d0b9920cac | ||
|
|
51d2b5225e | ||
|
|
563e8a2bd6 | ||
|
|
a30554e97c | ||
|
|
ef6e502ff0 | ||
|
|
93daaf5b5b | ||
|
|
70489b2fc2 | ||
|
|
27c45d8dda | ||
|
|
3123abfac3 | ||
|
|
522c6e01d2 | ||
|
|
14a31a2299 | ||
|
|
35baff8bac | ||
|
|
5969c227ab | ||
|
|
8badba26b8 | ||
|
|
24e3ad4e18 | ||
|
|
a66f83644b | ||
|
|
364dab6990 | ||
|
|
b960857fc2 | ||
|
|
65d3373ad3 | ||
|
|
3108817717 | ||
|
|
d44f279339 | ||
|
|
a83bb39d0f | ||
|
|
d62f76afa6 | ||
|
|
97c2917c16 | ||
|
|
3cd675bfff | ||
|
|
478093aa89 | ||
|
|
dcae1c5c04 | ||
|
|
6e9bee1be7 | ||
|
|
25d6e00b1a | ||
|
|
a47897bdf9 | ||
|
|
2c41de6648 | ||
|
|
dd1bed02e8 | ||
|
|
bd5edc7ae5 | ||
|
|
dfe932d053 | ||
|
|
99881db8bd | ||
|
|
0c1f3ed0b3 | ||
|
|
a811ab3aff | ||
|
|
5a28a796af | ||
|
|
4adb0c75bd | ||
|
|
4a16be2cba | ||
|
|
f8e6ba633a | ||
|
|
c7c8e2f3e3 | ||
|
|
eaf05305ff | ||
|
|
044623a360 | ||
|
|
07c05528ef | ||
|
|
c72e385a47 | ||
|
|
797966fd3d | ||
|
|
82d463e86e | ||
|
|
97c0f1c7b7 | ||
|
|
64507ab316 | ||
|
|
b9c4abe7dc | ||
|
|
6d315a5d16 | ||
|
|
187b7e117c | ||
|
|
f0e7be7d56 | ||
|
|
c6c1ad1b90 | ||
|
|
07fe29cc67 | ||
|
|
4929c66e60 | ||
|
|
3ef09da1df | ||
|
|
9e41f43ee2 | ||
|
|
2cbad4aed6 | ||
|
|
3247794e2f | ||
|
|
e946f49b64 | ||
|
|
0bff1b4afb | ||
|
|
8232698254 | ||
|
|
6a78aa7840 | ||
|
|
7383988988 | ||
|
|
e906ded0d1 | ||
|
|
032a7e71fe | ||
|
|
af8b2b6d9c | ||
|
|
c36292bfd0 | ||
|
|
1111afc031 | ||
|
|
54dbd7c0bd | ||
|
|
ef5bf87672 | ||
|
|
eb45e67784 | ||
|
|
1eacbd88b8 | ||
|
|
a89bd32eb0 | ||
|
|
56a2dc632b | ||
|
|
7dded52de2 | ||
|
|
8425a94729 | ||
|
|
7bf55fbc49 | ||
|
|
39349f3763 | ||
|
|
60c6158152 | ||
|
|
225e70a8d0 | ||
|
|
338a6f2114 | ||
|
|
cd7c7c3152 | ||
|
|
84748cda76 | ||
|
|
f94a61cc8a | ||
|
|
b51ffadd27 | ||
|
|
0f2c50f1f5 | ||
|
|
c8e2b027ee | ||
|
|
839c9e35c8 | ||
|
|
46eec3c8eb | ||
|
|
6ae11b5b2c | ||
|
|
ff733e0334 | ||
|
|
693d729ec6 | ||
|
|
2150c1d58e | ||
|
|
1273b063f4 | ||
|
|
a755633405 | ||
|
|
19579f0d9a | ||
|
|
ca583bffd5 | ||
|
|
5fee6d2d19 | ||
|
|
10f0f3038c | ||
|
|
73aba09eee | ||
|
|
035d655e72 | ||
|
|
f18c163408 | ||
|
|
28e5dcef52 | ||
|
|
f015cea590 | ||
|
|
05dd3fa0e7 | ||
|
|
05d83e487d | ||
|
|
21079a1315 | ||
|
|
947ab8a14d | ||
|
|
8ea7a28a77 | ||
|
|
758b6bd4dd | ||
|
|
0f6e845418 | ||
|
|
01a06d1f5c | ||
|
|
44dca68463 | ||
|
|
4e93330cb9 | ||
|
|
0640b41f00 | ||
|
|
b740cf9664 | ||
|
|
097927226b | ||
|
|
f8d1e2ac11 | ||
|
|
1f7990d6bb | ||
|
|
a484e9fb06 | ||
|
|
b505662ef9 | ||
|
|
3f5ab60fb4 | ||
|
|
2ccc6dc092 | ||
|
|
8e9ac18026 | ||
|
|
1d76578202 | ||
|
|
353c0a9ee7 | ||
|
|
3cf28ad6ce | ||
|
|
18b05bc56e | ||
|
|
54012eba23 | ||
|
|
2eb11731e2 | ||
|
|
02fd63ce20 | ||
|
|
7cfa08abc8 | ||
|
|
2c93bce9ad | ||
|
|
b20232db3c | ||
|
|
3b3350e648 | ||
|
|
32b3e416b3 | ||
|
|
abe6c90829 | ||
|
|
0a17ab9325 | ||
|
|
4e261c61ae | ||
|
|
800801177d | ||
|
|
b802d7903a | ||
|
|
ee98c0c587 | ||
|
|
1bc16fb31e | ||
|
|
43effd2b40 | ||
|
|
e8644f6f2a | ||
|
|
b48caaf465 | ||
|
|
8729701b66 | ||
|
|
29cb067769 | ||
|
|
ae8408bcab | ||
|
|
4998a48f99 | ||
|
|
3a9cf639bd | ||
|
|
5fa9f16c01 | ||
|
|
f6366e1e1f | ||
|
|
207d8f6030 | ||
|
|
5014ef2337 | ||
|
|
43ccc14162 | ||
|
|
e3a49f8213 | ||
|
|
270b56af1b | ||
|
|
39a88d2e43 | ||
|
|
913990bc62 | ||
|
|
c6eb795e76 | ||
|
|
9f590dbf2d | ||
|
|
414bf12f86 | ||
|
|
88c6d4bb20 | ||
|
|
d55f18f8e3 | ||
|
|
f1744890b1 | ||
|
|
c34d6d1162 | ||
|
|
81dbe36e99 | ||
|
|
ba99e21875 | ||
|
|
91442e100c | ||
|
|
feb2303e1f | ||
|
|
1ab04a7276 | ||
|
|
2acf518037 | ||
|
|
fe143c7dfa | ||
|
|
b39bb24fcf | ||
|
|
a855074588 | ||
|
|
0de621edf9 | ||
|
|
1903cb8f82 | ||
|
|
a762373ad6 | ||
|
|
64b305cf7a | ||
|
|
49ae549e89 | ||
|
|
097c23e437 | ||
|
|
786edb72df | ||
|
|
d458464e6b | ||
|
|
d834cec9b9 | ||
|
|
8614563b42 | ||
|
|
5bff5188ac | ||
|
|
e865a290de | ||
|
|
e3765ced78 | ||
|
|
2437546009 | ||
|
|
a3bacc76f1 | ||
|
|
cf40d0ae4d | ||
|
|
489ac04f86 | ||
|
|
19bb8e8c17 | ||
|
|
e07516585a | ||
|
|
f02b6d60a5 | ||
|
|
b03e75e3d1 | ||
|
|
a34d6d390e | ||
|
|
edb273ace5 | ||
|
|
c6c925d67a | ||
|
|
04940a1105 | ||
|
|
90633b9ce1 | ||
|
|
90fe5c5aca | ||
|
|
2e2673aff6 | ||
|
|
440793b5ff | ||
|
|
222cd41aa3 | ||
|
|
092fbd60d9 | ||
|
|
ec48d0ac29 | ||
|
|
bf2d7b3a16 | ||
|
|
13997caa32 | ||
|
|
3e889c398e | ||
|
|
858c0e67a1 | ||
|
|
957b3e1e85 | ||
|
|
3ce0a9c8c0 | ||
|
|
7de9214c99 | ||
|
|
402ed04189 | ||
|
|
059d6b0e0f | ||
|
|
563dc62c33 | ||
|
|
3f1f83f667 | ||
|
|
6d5f9035e6 | ||
|
|
7d47bffd53 | ||
|
|
d4acccb13c | ||
|
|
0a7e4b6840 | ||
|
|
4e0f3a30ee | ||
|
|
ba46eaa143 | ||
|
|
3c493511e9 | ||
|
|
12e8107492 | ||
|
|
5c7dedffb3 | ||
|
|
71a08c3237 | ||
|
|
d408ae7e10 | ||
|
|
386eb2d56b | ||
|
|
a2615339f7 | ||
|
|
cae6f91729 | ||
|
|
dbe0170249 | ||
|
|
188dbde2d6 | ||
|
|
96d11b7966 |
@@ -4,8 +4,8 @@ This open source repository contains the standard CodeQL libraries and queries t
|
||||
|
||||
## How do I learn CodeQL and run queries?
|
||||
|
||||
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed.
|
||||
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension to try out your queries on any open source project that's currently being analyzed.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
2
cpp/change-notes/2021-06-22-sql-tainted.md
Normal file
2
cpp/change-notes/2021-06-22-sql-tainted.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* The 'Uncontrolled data in SQL query' (cpp/sql-injection) query now supports the `libpqxx` library.
|
||||
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
@@ -0,0 +1,3 @@
|
||||
lgtm,codescanning
|
||||
* Increase precision to high for the "Static buffer overflow" query
|
||||
(`cpp/static-buffer-overflow`). This means the query is run and displayed by default on Code Scanning and LGTM.
|
||||
@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
|
||||
* char data[1]; // v
|
||||
* };
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
|
||||
* In addition, if the size of the structure is taken, there must be at least one instance
|
||||
* where a `c` pointer is allocated with additional space.
|
||||
* For example, holds for `c` if it occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c) + 100 * sizeof(char))
|
||||
* ```
|
||||
* but not if it only ever occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c))
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1.
|
||||
*/
|
||||
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
exists(int i |
|
||||
// `v` is the last field in `c`
|
||||
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
|
||||
v = c.getCanonicalMember(i) and
|
||||
// v is an array of size at most 1
|
||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
|
||||
not c instanceof Union
|
||||
) and
|
||||
// If the size is taken, then arithmetic is performed on the result at least once
|
||||
(
|
||||
// `sizeof(c)` is not taken
|
||||
not exists(SizeofOperator so |
|
||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
||||
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
||||
)
|
||||
or
|
||||
// or `sizeof(c)` is taken
|
||||
exists(SizeofOperator so |
|
||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
||||
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
||||
|
|
||||
// and arithmetic is performed on the result
|
||||
so.getParent*() instanceof AddExpr
|
||||
)
|
||||
)
|
||||
c = v.getDeclaringType() and
|
||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
|
||||
why = bufferVar and
|
||||
not memberMayBeVarSize(_, bufferVar) and
|
||||
not exists(Union bufferType |
|
||||
bufferType.getAMemberVariable() = why and
|
||||
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
|
||||
) and
|
||||
not result = 0 // zero sized arrays are likely to have special usage, for example
|
||||
or
|
||||
// behaving a bit like a 'union' overlapping other fields.
|
||||
@@ -85,13 +48,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
|
||||
)
|
||||
or
|
||||
exists(Union bufferType |
|
||||
bufferType.getAMemberVariable() = why and
|
||||
why = bufferVar and
|
||||
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
|
||||
result = bufferType.getSize()
|
||||
)
|
||||
)
|
||||
or
|
||||
// buffer is a fixed size dynamic allocation
|
||||
|
||||
@@ -93,6 +93,15 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
|
||||
fc.getArgument(i) = va
|
||||
)
|
||||
or
|
||||
// String argument to a formatting function (such as `printf`)
|
||||
exists(int n, FormatLiteral fl |
|
||||
fc.(FormattingFunctionCall).getConversionArgument(n) = va and
|
||||
fl = fc.(FormattingFunctionCall).getFormat() and
|
||||
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||
)
|
||||
or
|
||||
// Call to a wrapper function that requires null termination
|
||||
// (not itself adding a null terminator)
|
||||
exists(Function wrapper, int i, Parameter p, VariableAccess use |
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -550,6 +550,39 @@ module TaintedWithPath {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is flow from `arg` to `out` across a call that can by summarized by the flow
|
||||
* from `par` to `ret` within it, in the graph of data flow path explanations.
|
||||
*/
|
||||
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner())
|
||||
or
|
||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||
// of adding an edge out of it.
|
||||
exists(WrapPathNode sinkNode |
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
or
|
||||
// Same for the first node
|
||||
exists(WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner())
|
||||
)
|
||||
or
|
||||
// Finally, handle the case where the path goes directly from a source to a
|
||||
// sink, meaning that they both need to be translated.
|
||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
key = "semmle.label" and val = n.toString()
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -33,3 +33,6 @@ private import implementations.Recv
|
||||
private import implementations.Accept
|
||||
private import implementations.Poll
|
||||
private import implementations.Select
|
||||
private import implementations.MySql
|
||||
private import implementations.SqLite3
|
||||
private import implementations.PostgreSql
|
||||
|
||||
32
cpp/ql/lib/semmle/code/cpp/models/implementations/MySql.qll
Normal file
32
cpp/ql/lib/semmle/code/cpp/models/implementations/MySql.qll
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the MySql C API.
|
||||
* See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
/**
|
||||
* The `mysql_query` family of functions from the MySQL C API.
|
||||
*/
|
||||
private class MySqlExecutionFunction extends SqlExecutionFunction {
|
||||
MySqlExecutionFunction() {
|
||||
this.hasName(["mysql_query", "mysql_real_query", "mysql_real_query_nonblocking"])
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `mysql_real_escape_string` family of functions from the MySQL C API.
|
||||
*/
|
||||
private class MySqlBarrierFunction extends SqlBarrierFunction {
|
||||
MySqlBarrierFunction() {
|
||||
this.hasName(["mysql_real_escape_string", "mysql_real_escape_string_quote"])
|
||||
}
|
||||
|
||||
override predicate barrierSqlArgument(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(2) and
|
||||
output.isParameterDeref(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
private predicate pqxxTransactionSqlArgument(string function, int arg) {
|
||||
function = "exec" and arg = 0
|
||||
or
|
||||
function = "exec0" and arg = 0
|
||||
or
|
||||
function = "exec1" and arg = 0
|
||||
or
|
||||
function = "exec_n" and arg = 1
|
||||
or
|
||||
function = "exec_params" and arg = 0
|
||||
or
|
||||
function = "exec_params0" and arg = 0
|
||||
or
|
||||
function = "exec_params1" and arg = 0
|
||||
or
|
||||
function = "exec_params_n" and arg = 1
|
||||
or
|
||||
function = "query_value" and arg = 0
|
||||
or
|
||||
function = "stream" and arg = 0
|
||||
}
|
||||
|
||||
private predicate pqxxConnectionSqlArgument(string function, int arg) {
|
||||
function = "prepare" and arg = 1
|
||||
}
|
||||
|
||||
private predicate pqxxTransationClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in [
|
||||
"dbtransaction", "nontransaction", "basic_robusttransaction", "robusttransaction",
|
||||
"subtransaction", "transaction", "basic_transaction", "transaction_base", "work"
|
||||
]
|
||||
}
|
||||
|
||||
private predicate pqxxConnectionClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in ["connection_base", "basic_connection", "connection"]
|
||||
}
|
||||
|
||||
private predicate pqxxEscapeArgument(string function, int arg) {
|
||||
arg = 0 and
|
||||
function in ["esc", "esc_raw", "quote", "quote_raw", "quote_name", "quote_table", "esc_like"]
|
||||
}
|
||||
|
||||
private class PostgreSqlExecutionFunction extends SqlExecutionFunction {
|
||||
PostgreSqlExecutionFunction() {
|
||||
exists(Class c |
|
||||
this.getDeclaringType() = c and
|
||||
// transaction exec and connection prepare variations
|
||||
(
|
||||
pqxxTransationClassNames(c.getName(), c.getNamespace().getName()) and
|
||||
pqxxTransactionSqlArgument(this.getName(), _)
|
||||
or
|
||||
pqxxConnectionSqlArgument(this.getName(), _) and
|
||||
pqxxConnectionClassNames(c.getName(), c.getNamespace().getName())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) {
|
||||
exists(int argIndex |
|
||||
pqxxTransactionSqlArgument(this.getName(), argIndex)
|
||||
or
|
||||
pqxxConnectionSqlArgument(this.getName(), argIndex)
|
||||
|
|
||||
input.isParameterDeref(argIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class PostgreSqlBarrierFunction extends SqlBarrierFunction {
|
||||
PostgreSqlBarrierFunction() {
|
||||
exists(Class c |
|
||||
this.getDeclaringType() = c and
|
||||
// transaction and connection escape functions
|
||||
(
|
||||
pqxxTransationClassNames(c.getName(), c.getNamespace().getName()) or
|
||||
pqxxConnectionClassNames(c.getName(), c.getNamespace().getName())
|
||||
) and
|
||||
pqxxEscapeArgument(this.getName(), _)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate barrierSqlArgument(FunctionInput input, FunctionOutput output) {
|
||||
exists(int argIndex |
|
||||
input.isParameterDeref(argIndex) and
|
||||
output.isReturnValueDeref() and
|
||||
pqxxEscapeArgument(this.getName(), argIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the SQLite C API.
|
||||
* See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
/**
|
||||
* The `sqlite3_exec` and `sqlite3_prepare` families of functions from the SQLite C API.
|
||||
*/
|
||||
private class SqLite3ExecutionFunction extends SqlExecutionFunction {
|
||||
SqLite3ExecutionFunction() {
|
||||
this.hasName([
|
||||
"sqlite3_exec", "sqlite3_prepare", "sqlite3_prepare_v2", "sqlite3_prepare_v3",
|
||||
"sqlite3_prepare16", "sqlite3_prepare16_v2", "sqlite3_prepare16_v3"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
|
||||
}
|
||||
30
cpp/ql/lib/semmle/code/cpp/models/interfaces/Sql.qll
Normal file
30
cpp/ql/lib/semmle/code/cpp/models/interfaces/Sql.qll
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Provides abstract classes for modeling functions that execute and escape SQL query strings.
|
||||
* To extend this QL library, create a QL class extending `SqlExecutionFunction` or `SqlEscapeFunction`
|
||||
* with a characteristic predicate that selects the function or set of functions you are modeling.
|
||||
* Within that class, override the predicates provided by the class to match the way a
|
||||
* parameter flows into the function and, in the case of `SqlEscapeFunction`, out of the function.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
|
||||
/**
|
||||
* An abstract class that represents a function that executes an SQL query.
|
||||
*/
|
||||
abstract class SqlExecutionFunction extends Function {
|
||||
/**
|
||||
* Holds if `input` to this function represents SQL code to be executed.
|
||||
*/
|
||||
abstract predicate hasSqlArgument(FunctionInput input);
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract class that represents a function that is a barrier to an SQL query string.
|
||||
*/
|
||||
abstract class SqlBarrierFunction extends Function {
|
||||
/**
|
||||
* Holds if the `output` is a barrier to the SQL input `input` such that is it safe to pass to
|
||||
* an `SqlExecutionFunction`.
|
||||
*/
|
||||
abstract predicate barrierSqlArgument(FunctionInput input, FunctionOutput output);
|
||||
}
|
||||
@@ -29,8 +29,7 @@ predicate nanExcludingComparison(ComparisonOperation guard, boolean polarity) {
|
||||
*/
|
||||
private predicate excludesNan(RangeSsaDefinition def, VariableAccess v) {
|
||||
exists(VariableAccess inCond, ComparisonOperation guard, boolean branch, StackVariable lsv |
|
||||
def.isGuardPhi(inCond, guard, branch) and
|
||||
inCond.getTarget() = lsv and
|
||||
def.isGuardPhi(lsv, inCond, guard, branch) and
|
||||
v = def.getAUse(lsv) and
|
||||
guard.getAnOperand() = inCond and
|
||||
nanExcludingComparison(guard, branch)
|
||||
|
||||
@@ -94,10 +94,11 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use isGuardPhi/4 instead
|
||||
* If this definition is a phi node corresponding to a guard,
|
||||
* then return the variable access and the guard.
|
||||
*/
|
||||
predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
|
||||
deprecated predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
|
||||
guard_defn(va, guard, this, branch)
|
||||
}
|
||||
|
||||
@@ -142,9 +143,8 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
// below excludes definitions which can only reach guard phi
|
||||
// nodes by going through the corresponding guard.
|
||||
not exists(VariableAccess access |
|
||||
v = access.getTarget() and
|
||||
pred.contains(access) and
|
||||
this.isGuardPhi(access, _, _)
|
||||
this.isGuardPhi(v, access, _, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -433,10 +433,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
|
||||
private predicate phiDependsOnDef(
|
||||
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
|
||||
) {
|
||||
exists(VariableAccess access, Expr guard |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, _)
|
||||
|
|
||||
exists(VariableAccess access, Expr guard | phi.isGuardPhi(v, access, guard, _) |
|
||||
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
|
||||
exprDependsOnDef(access, srcDef, srcVar)
|
||||
)
|
||||
@@ -1204,8 +1201,7 @@ private float boolConversionUpperBound(Expr expr) {
|
||||
*/
|
||||
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
phi.isGuardPhi(v, access, guard, branch) and
|
||||
lowerBoundFromGuard(guard, access, guardLB, branch) and
|
||||
defLB = getFullyConvertedLowerBounds(access)
|
||||
|
|
||||
@@ -1230,8 +1226,7 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
/** See comment for `getPhiLowerBounds`, above. */
|
||||
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
phi.isGuardPhi(v, access, guard, branch) and
|
||||
upperBoundFromGuard(guard, access, guardUB, branch) and
|
||||
defUB = getFullyConvertedUpperBounds(access)
|
||||
|
|
||||
@@ -1493,8 +1488,7 @@ private predicate isNEPhi(
|
||||
exists(
|
||||
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
phi.isGuardPhi(v, access, cmp, branch) and
|
||||
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
|
||||
r = getValue(rExpr).toFloat() and
|
||||
@@ -1503,8 +1497,7 @@ private predicate isNEPhi(
|
||||
)
|
||||
or
|
||||
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, op, branch) and
|
||||
phi.isGuardPhi(v, access, op, branch) and
|
||||
eqZeroWithNegate(op, linearExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
|
||||
linearAccess(linearExpr, access, p, q) and
|
||||
@@ -1524,8 +1517,7 @@ private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, Vari
|
||||
or
|
||||
eqZeroWithNegate(cmp, _, false, branch)
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
phi.isGuardPhi(v, access, cmp, branch) and
|
||||
not isNEPhi(v, phi, access, _)
|
||||
)
|
||||
}
|
||||
@@ -1549,7 +1541,8 @@ private float getGuardedUpperBound(VariableAccess guardedAccess) {
|
||||
// that there is one predecessor, albeit somewhat conservative.
|
||||
exists(unique(BasicBlock b | b = def.(BasicBlock).getAPredecessor())) and
|
||||
guardedAccess = def.getAUse(v) and
|
||||
result = max(float ub | upperBoundFromGuard(guard, guardVa, ub, branch))
|
||||
result = max(float ub | upperBoundFromGuard(guard, guardVa, ub, branch)) and
|
||||
not convertedExprMightOverflow(guard.getAChild+())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1593,6 +1586,15 @@ private module SimpleRangeAnalysisCached {
|
||||
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
||||
}
|
||||
|
||||
/** Holds if the upper bound of `expr` may have been widened. This means the the upper bound is in practice likely to be overly wide. */
|
||||
cached
|
||||
predicate upperBoundMayBeWidened(Expr e) {
|
||||
isRecursiveExpr(e) and
|
||||
// Widening is not a problem if the post-analysis in `getGuardedUpperBound` has overridden the widening.
|
||||
// Note that the RHS of `<` may be multi-valued.
|
||||
not getGuardedUpperBound(e) < getTruncatedUpperBounds(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` has a provably empty range. For example:
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.security.SecurityOptions
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.Sql
|
||||
|
||||
/**
|
||||
* Extend this class to customize the security queries for
|
||||
@@ -34,13 +35,11 @@ class SecurityOptions extends string {
|
||||
* An argument to a function that is passed to a SQL server.
|
||||
*/
|
||||
predicate sqlArgument(string function, int arg) {
|
||||
// MySQL C API
|
||||
function = "mysql_query" and arg = 1
|
||||
or
|
||||
function = "mysql_real_query" and arg = 1
|
||||
or
|
||||
// SQLite3 C API
|
||||
function = "sqlite3_exec" and arg = 1
|
||||
exists(FunctionInput input, SqlExecutionFunction sql |
|
||||
sql.hasName(function) and
|
||||
input.isParameterDeref(arg) and
|
||||
sql.hasSqlArgument(input)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @precision medium
|
||||
* @precision high
|
||||
* @id cpp/static-buffer-overflow
|
||||
* @tags reliability
|
||||
* security
|
||||
@@ -55,6 +55,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
|
||||
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
|
||||
// Ensure that we don't have an upper bound on the array index that's less than the buffer size.
|
||||
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
|
||||
// The upper bounds analysis must not have been widended
|
||||
not upperBoundMayBeWidened(bufaccess.getArrayOffset().getFullyConverted()) and
|
||||
msg =
|
||||
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
|
||||
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
|
||||
@@ -130,11 +132,13 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) {
|
||||
(
|
||||
access > size
|
||||
or
|
||||
access = size and not exists(AddressOfExpr addof | bufaccess = addof.getOperand())
|
||||
access = size and
|
||||
not exists(AddressOfExpr addof | bufaccess = addof.getOperand()) and
|
||||
not exists(BuiltInOperationBuiltInOffsetOf offsetof | offsetof.getAChild() = bufaccess)
|
||||
) and
|
||||
msg =
|
||||
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
|
||||
access.toString() + "]' is accessed here."
|
||||
access.toString() + "]' may be accessed here."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,15 @@ class Configuration extends TaintTrackingConfiguration {
|
||||
}
|
||||
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
|
||||
super.isBarrier(e)
|
||||
or
|
||||
e.getUnspecifiedType() instanceof IntegralType
|
||||
or
|
||||
exists(SqlBarrierFunction sql, int arg, FunctionInput input |
|
||||
e = sql.getACallToThisFunction().getArgument(arg) and
|
||||
input.isParameterDeref(arg) and
|
||||
sql.barrierSqlArgument(input, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <pqxx/pqxx>
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
if (argc != 2) {
|
||||
throw std::runtime_error("Give me a string!");
|
||||
}
|
||||
|
||||
pqxx::connection c;
|
||||
pqxx::work w(c);
|
||||
|
||||
// BAD
|
||||
char *userName = argv[1];
|
||||
char query1[1000] = {0};
|
||||
sprintf(query1, "SELECT UID FROM USERS where name = \"%s\"", userName);
|
||||
pqxx::row r = w.exec1(query1);
|
||||
w.commit();
|
||||
std::cout << r[0].as<int>() << std::endl;
|
||||
|
||||
// GOOD
|
||||
pqxx::result r2 = w.exec("SELECT " + w.quote(argv[1]));
|
||||
w.commit();
|
||||
std::cout << r2[0][0].c_str() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The code passes user input as part of a SQL query without escaping special elements.
|
||||
It generates a SQL query to Postgres using <code>sprintf</code>,
|
||||
with the user-supplied data directly passed as an argument
|
||||
to <code>sprintf</code>. This leaves the code vulnerable to attack by SQL Injection.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Use a library routine to escape characters in the user-supplied
|
||||
string before converting it to SQL. Use <code>esc</code> and <code>quote</code> pqxx library functions.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<sample src="SqlPqxxTainted.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>MSDN Library: <a href="https://docs.microsoft.com/en-us/sql/relational-databases/security/sql-injection">SQL Injection</a>.</li>
|
||||
|
||||
|
||||
<!-- LocalWords: SQL CWE
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* @name Uncontrolled data in SQL query to Postgres
|
||||
* @description Including user-supplied data in a SQL query to Postgres
|
||||
* without neutralizing special elements can make code
|
||||
* vulnerable to SQL Injection.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/sql-injection-via-pqxx
|
||||
* @tags security
|
||||
* external/cwe/cwe-089
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
predicate pqxxTransationClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in [
|
||||
"dbtransaction", "nontransaction", "basic_robusttransaction", "robusttransaction",
|
||||
"subtransaction", "transaction", "basic_transaction", "transaction_base", "work"
|
||||
]
|
||||
}
|
||||
|
||||
predicate pqxxConnectionClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in ["connection_base", "basic_connection", "connection"]
|
||||
}
|
||||
|
||||
predicate pqxxTransactionSqlArgument(string function, int arg) {
|
||||
function = "exec" and arg = 0
|
||||
or
|
||||
function = "exec0" and arg = 0
|
||||
or
|
||||
function = "exec1" and arg = 0
|
||||
or
|
||||
function = "exec_n" and arg = 1
|
||||
or
|
||||
function = "exec_params" and arg = 0
|
||||
or
|
||||
function = "exec_params0" and arg = 0
|
||||
or
|
||||
function = "exec_params1" and arg = 0
|
||||
or
|
||||
function = "exec_params_n" and arg = 1
|
||||
or
|
||||
function = "query_value" and arg = 0
|
||||
or
|
||||
function = "stream" and arg = 0
|
||||
}
|
||||
|
||||
predicate pqxxConnectionSqlArgument(string function, int arg) { function = "prepare" and arg = 1 }
|
||||
|
||||
Expr getPqxxSqlArgument() {
|
||||
exists(FunctionCall fc, Expr e, int argIndex, UserType t |
|
||||
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
|
||||
e = fc.getQualifier() and
|
||||
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
|
||||
// and return pointer to a connection/transation object
|
||||
e.getType().refersTo(t) and
|
||||
// transaction exec and connection prepare variations
|
||||
(
|
||||
pqxxTransationClassNames(t.getName(), t.getNamespace().getName()) and
|
||||
pqxxTransactionSqlArgument(fc.getTarget().getName(), argIndex)
|
||||
or
|
||||
pqxxConnectionClassNames(t.getName(), t.getNamespace().getName()) and
|
||||
pqxxConnectionSqlArgument(fc.getTarget().getName(), argIndex)
|
||||
) and
|
||||
result = fc.getArgument(argIndex)
|
||||
)
|
||||
}
|
||||
|
||||
predicate pqxxEscapeArgument(string function, int arg) {
|
||||
arg = 0 and
|
||||
function in ["esc", "esc_raw", "quote", "quote_raw", "quote_name", "quote_table", "esc_like"]
|
||||
}
|
||||
|
||||
predicate isEscapedPqxxArgument(Expr argExpr) {
|
||||
exists(FunctionCall fc, Expr e, int argIndex, UserType t |
|
||||
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
|
||||
e = fc.getQualifier() and
|
||||
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
|
||||
// and return pointer to a connection/transation object
|
||||
e.getType().refersTo(t) and
|
||||
// transaction and connection escape functions
|
||||
(
|
||||
pqxxTransationClassNames(t.getName(), t.getNamespace().getName()) or
|
||||
pqxxConnectionClassNames(t.getName(), t.getNamespace().getName())
|
||||
) and
|
||||
pqxxEscapeArgument(fc.getTarget().getName(), argIndex) and
|
||||
// is escaped arg == argExpr
|
||||
argExpr = fc.getArgument(argIndex)
|
||||
)
|
||||
}
|
||||
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "SqlPqxxTainted" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink.asExpr() = getPqxxSqlArgument() }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { isEscapedPqxxArgument(node.asExpr()) }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Configuration config, string taintCause
|
||||
where
|
||||
config.hasFlowPath(source, sink) and
|
||||
isUserInput(source.getNode().asExpr(), taintCause)
|
||||
select sink, source, sink, "This argument to a SQL query function is derived from $@", source,
|
||||
"user input (" + taintCause + ")"
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @name unsigned to signed used in pointer arithmetic
|
||||
* @description finds unsigned to signed conversions used in pointer arithmetic, potentially causing an out-of-bound access
|
||||
* @id cpp/sign-conversion-pointer-arithmetic
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-787
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.security.Overflow
|
||||
|
||||
from FunctionCall call, Function f, Parameter p, DataFlow::Node sink, PointerArithmeticOperation pao
|
||||
where
|
||||
f = call.getTarget() and
|
||||
p = f.getAParameter() and
|
||||
p.getUnspecifiedType().(IntegralType).isSigned() and
|
||||
call.getArgument(p.getIndex()).getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
pao.getAnOperand() = sink.asExpr() and
|
||||
not exists(Operation a | guardedLesser(a, sink.asExpr())) and
|
||||
not exists(Operation b | guardedGreater(b, call.getArgument(p.getIndex()))) and
|
||||
not call.getArgument(p.getIndex()).isConstant() and
|
||||
DataFlow::localFlow(DataFlow::parameterNode(p), sink) and
|
||||
p.getUnspecifiedType().getSize() < 8
|
||||
select call,
|
||||
"This call: $@ passes an unsigned int to a function that requires a signed int: $@. And then used in pointer arithmetic: $@",
|
||||
call, call.toString(), f, f.toString(), sink, sink.toString()
|
||||
@@ -599,6 +599,10 @@
|
||||
| test.c:675:7:675:7 | y | -2147483648 |
|
||||
| test.c:684:7:684:7 | x | -2147483648 |
|
||||
| test.c:689:7:689:7 | x | -2147483648 |
|
||||
| test.c:696:8:696:8 | x | 2147483647 |
|
||||
| test.c:696:12:696:12 | y | 256 |
|
||||
| test.c:697:9:697:9 | x | 2147483647 |
|
||||
| test.c:698:9:698:9 | y | 256 |
|
||||
| test.cpp:10:7:10:7 | b | -2147483648 |
|
||||
| test.cpp:11:5:11:5 | x | -2147483648 |
|
||||
| test.cpp:13:10:13:10 | x | -2147483648 |
|
||||
|
||||
@@ -689,3 +689,12 @@ label:
|
||||
out(x);
|
||||
goto label;
|
||||
}
|
||||
|
||||
void test_overflow() {
|
||||
const int x = 2147483647; // 2^31-1
|
||||
const int y = 256;
|
||||
if ((x + y) <= 512) {
|
||||
out(x);
|
||||
out(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,6 +599,10 @@
|
||||
| test.c:675:7:675:7 | y | 2147483647 |
|
||||
| test.c:684:7:684:7 | x | 2147483647 |
|
||||
| test.c:689:7:689:7 | x | 15 |
|
||||
| test.c:696:8:696:8 | x | 2147483647 |
|
||||
| test.c:696:12:696:12 | y | 256 |
|
||||
| test.c:697:9:697:9 | x | 2147483647 |
|
||||
| test.c:698:9:698:9 | y | 256 |
|
||||
| test.cpp:10:7:10:7 | b | 2147483647 |
|
||||
| test.cpp:11:5:11:5 | x | 2147483647 |
|
||||
| test.cpp:13:10:13:10 | x | 2147483647 |
|
||||
|
||||
@@ -5,14 +5,10 @@
|
||||
| test2.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
||||
| test2.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
||||
| test2.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' is accessed here. |
|
||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is accessed here. |
|
||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' is accessed here. |
|
||||
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' is accessed here. |
|
||||
| test.c:47:3:47:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
||||
| test.c:54:3:54:26 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
||||
| test.c:61:3:61:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
|
||||
| test.c:72:3:72:11 | access to array | Potential buffer-overflow: 'buf' has size 1 but 'buf[1]' is accessed here. |
|
||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' may be accessed here. |
|
||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' may be accessed here. |
|
||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' may be accessed here. |
|
||||
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' may be accessed here. |
|
||||
| test.cpp:19:3:19:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer1' has 3 elements. |
|
||||
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |
|
||||
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
|
||||
|
||||
@@ -44,21 +44,21 @@ void union_test() {
|
||||
union u u;
|
||||
u.ptr[0] = 0; // GOOD
|
||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||
u.ptr[sizeof(u)] = 0; // BAD
|
||||
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_struct_union() {
|
||||
struct { union u u; } v;
|
||||
v.u.ptr[0] = 0; // GOOD
|
||||
v.u.ptr[sizeof(union u)-1] = 0; // GOOD
|
||||
v.u.ptr[sizeof(union u)] = 0; // BAD
|
||||
v.u.ptr[sizeof(union u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void union_test2() {
|
||||
union { char ptr[1]; unsigned long value; } u;
|
||||
u.ptr[0] = 0; // GOOD
|
||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||
u.ptr[sizeof(u)] = 0; // BAD
|
||||
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -69,5 +69,5 @@ typedef struct {
|
||||
void test_alloc() {
|
||||
// Special case of taking sizeof without any addition or multiplications
|
||||
var_buf *b = malloc(sizeof(var_buf));
|
||||
b->buf[1] = 0; // BAD
|
||||
b->buf[1] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
@@ -23,3 +23,5 @@
|
||||
| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 |
|
||||
| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer |
|
||||
| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer |
|
||||
| test.cpp:444:10:444:15 | buffer | Variable $@ may not be null terminated. | test.cpp:442:8:442:13 | buffer | buffer |
|
||||
| test.cpp:450:16:450:21 | buffer | Variable $@ may not be null terminated. | test.cpp:448:8:448:13 | buffer | buffer |
|
||||
|
||||
@@ -433,3 +433,36 @@ void test_read_fread(int read_src, FILE *s)
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
void test_printf(char *str)
|
||||
{
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
printf(buffer, ""); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
printf("%s", buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char *copied_str = (char *)malloc(len);
|
||||
|
||||
memcpy(copied_str, str, len);
|
||||
printf("%s", copied_str); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char *copied_str = (char *)malloc(len + 1);
|
||||
|
||||
memcpy(copied_str, str, len + 1);
|
||||
printf("%s", copied_str); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ edges
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | semmle.label | ... + ... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | semmle.label | fgets output argument |
|
||||
|
||||
@@ -5,6 +5,7 @@ edges
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName |
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection |
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.c:9:23:9:26 | argv | semmle.label | argv |
|
||||
| test.c:9:23:9:26 | argv | semmle.label | argv |
|
||||
|
||||
@@ -24,6 +24,7 @@ edges
|
||||
| search.c:55:17:55:25 | raw_query indirection | search.c:14:24:14:28 | *query |
|
||||
| search.c:57:5:57:15 | raw_query | search.c:22:24:22:28 | query |
|
||||
| search.c:57:17:57:25 | raw_query indirection | search.c:22:24:22:28 | *query |
|
||||
subpaths
|
||||
nodes
|
||||
| search.c:14:24:14:28 | *query | semmle.label | *query |
|
||||
| search.c:14:24:14:28 | query | semmle.label | query |
|
||||
|
||||
@@ -5,6 +5,15 @@ edges
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection |
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.c:15:20:15:23 | argv | semmle.label | argv |
|
||||
| test.c:15:20:15:23 | argv | semmle.label | argv |
|
||||
@@ -13,5 +22,15 @@ nodes
|
||||
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
|
||||
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
|
||||
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
|
||||
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
|
||||
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
|
||||
#select
|
||||
| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:15:20:15:23 | argv | user input (argv) |
|
||||
| test.cpp:43:27:43:33 | access to array | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)) | test.cpp:43:27:43:30 | argv | user input (argv) |
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
int sprintf(char* str, const char* format, ...);
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
};
|
||||
|
||||
typedef basic_string<char> string;
|
||||
}
|
||||
|
||||
namespace pqxx {
|
||||
struct connection {};
|
||||
|
||||
struct row {};
|
||||
struct result {};
|
||||
|
||||
struct work {
|
||||
work(connection&);
|
||||
|
||||
row exec1(const char*);
|
||||
result exec(const std::string&);
|
||||
std::string quote(const char*);
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
pqxx::connection c;
|
||||
pqxx::work w(c);
|
||||
|
||||
pqxx::row r = w.exec1(argv[1]); // BAD
|
||||
|
||||
pqxx::result r2 = w.exec(w.quote(argv[1])); // GOOD
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ edges
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:73:17:73:22 | data | test.cpp:37:73:37:76 | data |
|
||||
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | *data |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:37:73:37:76 | *data | semmle.label | *data |
|
||||
| test.cpp:37:73:37:76 | data | semmle.label | data |
|
||||
|
||||
@@ -47,6 +47,7 @@ edges
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | (const char *)... |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:24:30:24:36 | *command | semmle.label | *command |
|
||||
| test.cpp:24:30:24:36 | command | semmle.label | command |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
edges
|
||||
subpaths
|
||||
nodes
|
||||
#select
|
||||
|
||||
@@ -72,12 +72,9 @@
|
||||
| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:15:7:15:11 | small | destination buffer |
|
||||
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:16:7:16:11 | large | destination buffer |
|
||||
| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:34:14:34:18 | large | destination buffer |
|
||||
| var_size_struct.cpp:54:5:54:14 | access to array | This array indexing operation accesses byte offset 1 but the $@ is only 1 byte. | var_size_struct.cpp:32:8:32:10 | str | array |
|
||||
| var_size_struct.cpp:55:5:55:14 | access to array | This array indexing operation accesses byte offset 1 but the $@ is only 1 byte. | var_size_struct.cpp:38:8:38:10 | str | array |
|
||||
| var_size_struct.cpp:71:3:71:8 | call to memset | This 'memset' operation accesses 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
||||
| var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'strncpy' operation may access 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer |
|
||||
| var_size_struct.cpp:87:3:87:19 | access to array | This array indexing operation accesses byte offset 67 but the $@ is only 64 bytes. | var_size_struct.cpp:78:7:78:14 | elements | array |
|
||||
| var_size_struct.cpp:99:3:99:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
| var_size_struct.cpp:101:3:101:8 | call to memset | This 'memset' operation accesses 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
| var_size_struct.cpp:103:3:103:9 | call to strncpy | This 'strncpy' operation may access 129 bytes but the $@ is only 128 bytes. | var_size_struct.cpp:92:8:92:10 | str | destination buffer |
|
||||
| var_size_struct.cpp:169:3:169:8 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 1 byte. | var_size_struct.cpp:125:17:125:19 | arr | destination buffer |
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
| tests.cpp:163:3:163:11 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||
| tests.cpp:164:8:164:16 | access to array | Potential buffer-overflow: counter 'k' <= 100 but 'buffer' has 100 elements. |
|
||||
| tests.cpp:245:42:245:42 | 6 | Potential buffer-overflow: 'global_array_5' has size 5 not 6. |
|
||||
| tests.cpp:349:2:349:14 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
|
||||
| tests.cpp:350:17:350:29 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' is accessed here. |
|
||||
| var_size_struct.cpp:54:5:54:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
|
||||
| var_size_struct.cpp:55:5:55:14 | access to array | Potential buffer-overflow: 'str' has size 1 but 'str[1]' is accessed here. |
|
||||
| tests.cpp:349:2:349:14 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' may be accessed here. |
|
||||
| tests.cpp:350:17:350:29 | access to array | Potential buffer-overflow: 'charArray' has size 10 but 'charArray[10]' may be accessed here. |
|
||||
| var_size_struct.cpp:103:39:103:41 | 129 | Potential buffer-overflow: 'str' has size 128 not 129. |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
edges
|
||||
subpaths
|
||||
nodes
|
||||
#select
|
||||
|
||||
@@ -51,8 +51,8 @@ void testVarString(int n) {
|
||||
s1->str[1] = '?'; // GOOD
|
||||
s2->str[1] = '?'; // GOOD
|
||||
s3->str[1] = '?'; // GOOD
|
||||
s4->str[1] = '?'; // BAD
|
||||
s5->str[1] = '?'; // BAD
|
||||
s4->str[1] = '?'; // BAD [NOT DETECTED]
|
||||
s5->str[1] = '?'; // BAD [NOT DETECTED]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ void useVarStruct34(varStruct5 *vs5) {
|
||||
|
||||
void testVarStruct34(varStruct3 *vs3, varStruct4 *vs4, varStruct5 *vs5, varStruct6 *vs6, varStruct7 *vs7, varStruct8 *vs8, varStruct9 *vs9) {
|
||||
memset(vs3->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||
memset(vs4->arr, 'x', 100); // BAD: it's not variable size, so this is a buffer overflow
|
||||
memset(vs4->arr, 'x', 100); // BAD: [NOT DETECTED] it's not variable size, so this is a buffer overflow
|
||||
memset(vs5->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||
memset(vs6->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||
memset(vs7->arr, 'x', 100); // GOOD: it's variable size, we don't know how big so shouldn't flag
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
| var_size_struct.cpp:13:8:13:17 | VarString1 | var_size_struct.cpp:15:8:15:10 | str |
|
||||
| var_size_struct.cpp:18:8:18:17 | VarString2 | var_size_struct.cpp:20:8:20:10 | str |
|
||||
| var_size_struct.cpp:24:8:24:17 | VarString3 | var_size_struct.cpp:26:8:26:10 | str |
|
||||
| var_size_struct.cpp:30:8:30:17 | VarString4 | var_size_struct.cpp:32:8:32:10 | str |
|
||||
| var_size_struct.cpp:36:8:36:17 | VarString5 | var_size_struct.cpp:38:8:38:10 | str |
|
||||
| var_size_struct.cpp:36:8:36:17 | VarString5 | var_size_struct.cpp:39:8:39:11 | str2 |
|
||||
| var_size_struct.cpp:61:8:61:17 | varStruct1 | var_size_struct.cpp:63:8:63:11 | data |
|
||||
| var_size_struct.cpp:76:8:76:17 | varStruct2 | var_size_struct.cpp:78:7:78:14 | elements |
|
||||
| var_size_struct.cpp:106:8:106:20 | notVarStruct2 | var_size_struct.cpp:107:8:107:10 | str |
|
||||
| var_size_struct.cpp:119:8:119:17 | varStruct3 | var_size_struct.cpp:121:17:121:19 | arr |
|
||||
| var_size_struct.cpp:123:8:123:17 | varStruct4 | var_size_struct.cpp:125:17:125:19 | arr |
|
||||
| var_size_struct.cpp:127:8:127:17 | varStruct5 | var_size_struct.cpp:129:17:129:19 | arr |
|
||||
| var_size_struct.cpp:131:8:131:17 | varStruct6 | var_size_struct.cpp:133:17:133:19 | arr |
|
||||
| var_size_struct.cpp:135:8:135:17 | varStruct7 | var_size_struct.cpp:137:17:137:19 | arr |
|
||||
| var_size_struct.cpp:139:8:139:17 | varStruct8 | var_size_struct.cpp:141:9:141:11 | arr |
|
||||
| var_size_struct.cpp:143:8:143:17 | varStruct9 | var_size_struct.cpp:145:17:145:19 | arr |
|
||||
| var_size_struct.cpp:181:8:181:18 | PseudoUnion | var_size_struct.cpp:183:7:183:10 | data |
|
||||
|
||||
@@ -49,6 +49,7 @@ edges
|
||||
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
|
||||
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array indirection |
|
||||
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| tests.c:28:22:28:25 | argv | semmle.label | argv |
|
||||
| tests.c:28:22:28:25 | argv | semmle.label | argv |
|
||||
|
||||
@@ -17,6 +17,7 @@ edges
|
||||
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data |
|
||||
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection |
|
||||
| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | semmle.label | recv output argument |
|
||||
| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | semmle.label | ... + ... |
|
||||
|
||||
@@ -247,6 +247,13 @@ edges
|
||||
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
||||
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
||||
| argvLocal.c:170:15:170:26 | i10 indirection | argvLocal.c:9:25:9:31 | *correct |
|
||||
subpaths
|
||||
| argvLocal.c:117:2:117:13 | i3 | argvLocal.c:9:25:9:31 | correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:117:15:117:16 | printWrapper output argument |
|
||||
| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:117:15:117:16 | printWrapper output argument |
|
||||
| argvLocal.c:122:2:122:13 | i4 | argvLocal.c:9:25:9:31 | correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:122:15:122:16 | printWrapper output argument |
|
||||
| argvLocal.c:122:15:122:16 | i4 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:122:15:122:16 | printWrapper output argument |
|
||||
| argvLocal.c:128:2:128:13 | i5 | argvLocal.c:9:25:9:31 | correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:128:15:128:16 | printWrapper output argument |
|
||||
| argvLocal.c:128:15:128:16 | i5 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:128:15:128:16 | printWrapper output argument |
|
||||
nodes
|
||||
| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct |
|
||||
| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct |
|
||||
|
||||
@@ -51,6 +51,7 @@ edges
|
||||
| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... |
|
||||
| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 |
|
||||
| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument |
|
||||
| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
edges
|
||||
subpaths
|
||||
nodes
|
||||
#select
|
||||
|
||||
@@ -46,6 +46,7 @@ edges
|
||||
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... |
|
||||
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
|
||||
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
|
||||
|
||||
@@ -71,6 +71,7 @@ edges
|
||||
| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 |
|
||||
| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 indirection |
|
||||
| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| ifs.c:61:8:61:11 | argv | semmle.label | argv |
|
||||
| ifs.c:61:8:61:11 | argv | semmle.label | argv |
|
||||
|
||||
@@ -3,6 +3,7 @@ edges
|
||||
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
|
||||
subpaths
|
||||
nodes
|
||||
| examples.cpp:63:26:63:30 | & ... | semmle.label | & ... |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument |
|
||||
|
||||
@@ -73,6 +73,7 @@ edges
|
||||
| test.cpp:305:18:305:21 | Chi | test.cpp:308:10:308:27 | ... * ... |
|
||||
| test.cpp:305:18:305:21 | Chi | test.cpp:308:10:308:27 | ... * ... |
|
||||
| test.cpp:305:18:305:21 | get_size output argument [[]] | test.cpp:305:18:305:21 | Chi |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:40:21:40:24 | argv | semmle.label | argv |
|
||||
| test.cpp:40:21:40:24 | argv | semmle.label | argv |
|
||||
|
||||
@@ -23,6 +23,7 @@ edges
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
subpaths
|
||||
nodes
|
||||
| test2.cpp:12:21:12:21 | v | semmle.label | v |
|
||||
| test2.cpp:14:11:14:11 | v | semmle.label | v |
|
||||
|
||||
@@ -17,6 +17,7 @@ edges
|
||||
| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address |
|
||||
| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address |
|
||||
| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:16:25:16:30 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... |
|
||||
|
||||
@@ -5,6 +5,7 @@ edges
|
||||
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input |
|
||||
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input indirection |
|
||||
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:54:17:54:20 | argv | semmle.label | argv |
|
||||
| test.cpp:54:17:54:20 | argv | semmle.label | argv |
|
||||
|
||||
@@ -7,6 +7,7 @@ edges
|
||||
| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp |
|
||||
| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:10:41:38 | ! ... |
|
||||
| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:16 | call to strcmp |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:20:29:20:34 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... |
|
||||
|
||||
@@ -165,7 +165,6 @@ namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
if (environment is not null)
|
||||
environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value);
|
||||
pi.Environment["CODEQL_REDUCE_FILES_FOLDERS_RELATIONS"] = "true";
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
2
csharp/change-notes/2021-09-09-service-stack-support.md
Normal file
2
csharp/change-notes/2021-09-09-service-stack-support.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* added support for ServiceStack framework with support for SQL injection, XSS and external API calls
|
||||
@@ -10,7 +10,6 @@ extra_env_vars:
|
||||
CORECLR_ENABLE_PROFILING: "1"
|
||||
CORECLR_PROFILER: "{A3C70A64-7D41-4A94-A3F6-FD47D9259997}"
|
||||
CORECLR_PROFILER_PATH_64: "${env.CODEQL_EXTRACTOR_CSHARP_ROOT}/tools/${env.CODEQL_PLATFORM}/clrtracer64${env.CODEQL_PLATFORM_DLL_EXTENSION}"
|
||||
CODEQL_REDUCE_FILES_FOLDERS_RELATIONS: "true"
|
||||
file_types:
|
||||
- name: cs
|
||||
display_name: C# sources
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
package,sink,source,summary,sink:html,sink:xss,source:local,summary:taint
|
||||
System,5,3,13,4,1,3,13
|
||||
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint
|
||||
Dapper,55,,,,,,55,,,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,
|
||||
MySql.Data.MySqlClient,48,,,,,,48,,,
|
||||
ServiceStack,194,,7,27,,75,92,,,7
|
||||
System,28,3,13,,4,,23,1,3,13
|
||||
|
||||
|
@@ -7,6 +7,8 @@ C# framework & library support
|
||||
:widths: auto
|
||||
|
||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
||||
System,"``System.*``, ``System``",3,13,5,5
|
||||
Totals,,3,13,5,5
|
||||
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
||||
System,"``System.*``, ``System``",3,13,28,5
|
||||
Others,"``Dapper``, ``Microsoft.ApplicationBlocks.Data``, ``MySql.Data.MySqlClient``",,,131,
|
||||
Totals,,3,20,353,5
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
Framework name,URL,Namespace prefixes
|
||||
System,,System.* System
|
||||
ServiceStack,https://servicestack.net/,ServiceStack.* ServiceStack
|
||||
|
||||
|
@@ -17,7 +17,7 @@ module Gvn {
|
||||
string getNameNested(Type t) {
|
||||
if not t instanceof NestedType or t.(NestedType).getDeclaringType() instanceof GenericType
|
||||
then result = t.getName()
|
||||
else result = getNameNested(t.(NestedType).getDeclaringType()) + "." + t.getName()
|
||||
else result = getNameNested(t.(NestedType).getDeclaringType()) + "+" + t.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,79 +326,53 @@ module Gvn {
|
||||
getTypeArgument(k, t, i) = TTypeParameterGvnType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Hold if (non-type-parameters) `arg1` and `arg2` are unifiable, and both are
|
||||
* the `i`th type argument of a compound type of kind `k`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate unifiableNonTypeParameterTypeArguments(
|
||||
CompoundTypeKind k, GvnTypeArgument arg1, GvnTypeArgument arg2, int i
|
||||
) {
|
||||
exists(int j |
|
||||
arg1 = getNonTypeParameterTypeArgument(k, _, i) and
|
||||
arg2 = getNonTypeParameterTypeArgument(k, _, j) and
|
||||
i <= j and
|
||||
j <= i
|
||||
|
|
||||
arg1 = arg2
|
||||
or
|
||||
unifiable(arg1, arg2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hold if `arg1` and `arg2` are unifiable, and both are the `i`th type argument
|
||||
* of a compound type of kind `k`.
|
||||
*
|
||||
* `subsumes` indicates whether `arg1` in fact subsumes `arg2`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate unifiableTypeArguments(
|
||||
CompoundTypeKind k, GvnTypeArgument arg1, GvnTypeArgument arg2, int i
|
||||
CompoundTypeKind k, GvnTypeArgument arg1, GvnTypeArgument arg2, int i, boolean subsumes
|
||||
) {
|
||||
unifiableNonTypeParameterTypeArguments(k, arg1, arg2, i)
|
||||
or
|
||||
exists(int j |
|
||||
arg1 = TTypeParameterGvnType() and
|
||||
typeArgumentIsTypeParameter(k, _, i) and
|
||||
arg2 = getTypeArgument(k, _, j) and
|
||||
i <= j and
|
||||
j <= i
|
||||
arg1 = getNonTypeParameterTypeArgument(k, _, pragma[only_bind_into](i)) and
|
||||
arg2 = getNonTypeParameterTypeArgument(k, _, pragma[only_bind_into](i)) and
|
||||
(
|
||||
arg1 = arg2 and
|
||||
subsumes = true
|
||||
or
|
||||
unifiable(arg1, arg2, subsumes)
|
||||
)
|
||||
or
|
||||
exists(int j |
|
||||
arg1 = getTypeArgument(k, _, i) and
|
||||
typeArgumentIsTypeParameter(k, _, j) and
|
||||
arg2 = TTypeParameterGvnType() and
|
||||
i <= j and
|
||||
j <= i
|
||||
)
|
||||
arg1 = TTypeParameterGvnType() and
|
||||
typeArgumentIsTypeParameter(k, _, pragma[only_bind_into](i)) and
|
||||
arg2 = getTypeArgument(k, _, pragma[only_bind_into](i)) and
|
||||
subsumes = true
|
||||
or
|
||||
arg1 = getNonTypeParameterTypeArgument(k, _, pragma[only_bind_into](i)) and
|
||||
typeArgumentIsTypeParameter(k, _, pragma[only_bind_into](i)) and
|
||||
arg2 = TTypeParameterGvnType() and
|
||||
subsumes = false
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate unifiableSingle0(
|
||||
CompoundTypeKind k, ConstructedGvnType t2, GvnTypeArgument arg1, GvnTypeArgument arg2
|
||||
CompoundTypeKind k, ConstructedGvnType t2, GvnTypeArgument arg1, GvnTypeArgument arg2,
|
||||
boolean subsumes
|
||||
) {
|
||||
unifiableTypeArguments(k, arg1, arg2, 0) and
|
||||
unifiableTypeArguments(k, arg1, arg2, 0, subsumes) and
|
||||
arg2 = getTypeArgument(k, t2, 0) and
|
||||
k.getNumberOfTypeParameters() = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type arguments of types `t1` and `t2` are unifiable, `t1`
|
||||
* and `t2` are of the same kind, and the number of type arguments is 1.
|
||||
*/
|
||||
private predicate unifiableSingle(ConstructedGvnType t1, ConstructedGvnType t2) {
|
||||
exists(CompoundTypeKind k, GvnTypeArgument arg1, GvnTypeArgument arg2 |
|
||||
unifiableSingle0(k, t2, arg1, arg2) and
|
||||
arg1 = getTypeArgument(k, t1, 0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate unifiableMultiple01Aux0(
|
||||
CompoundTypeKind k, ConstructedGvnType t2, GvnTypeArgument arg10, GvnTypeArgument arg21
|
||||
CompoundTypeKind k, ConstructedGvnType t2, GvnTypeArgument arg10, GvnTypeArgument arg21,
|
||||
boolean subsumes
|
||||
) {
|
||||
exists(GvnTypeArgument arg20 |
|
||||
unifiableTypeArguments(k, arg10, arg20, 0) and
|
||||
unifiableTypeArguments(k, arg10, arg20, 0, subsumes) and
|
||||
arg20 = getTypeArgument(k, t2, 0) and
|
||||
arg21 = getTypeArgument(k, t2, 1)
|
||||
)
|
||||
@@ -406,43 +380,24 @@ module Gvn {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate unifiableMultiple01Aux1(
|
||||
CompoundTypeKind k, ConstructedGvnType t1, GvnTypeArgument arg10, GvnTypeArgument arg21
|
||||
CompoundTypeKind k, ConstructedGvnType t1, GvnTypeArgument arg10, GvnTypeArgument arg21,
|
||||
boolean subsumes
|
||||
) {
|
||||
exists(GvnTypeArgument arg11 |
|
||||
unifiableTypeArguments(k, arg11, arg21, 1) and
|
||||
unifiableTypeArguments(k, arg11, arg21, 1, subsumes) and
|
||||
arg10 = getTypeArgument(k, t1, 0) and
|
||||
arg11 = getTypeArgument(k, t1, 1)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the first two type arguments of types `t1` and `t2` are unifiable,
|
||||
* and both `t1` and `t2` are of kind `k`.
|
||||
*/
|
||||
private predicate unifiableMultiple01(
|
||||
CompoundTypeKind k, ConstructedGvnType t1, ConstructedGvnType t2
|
||||
) {
|
||||
exists(GvnTypeArgument arg10, GvnTypeArgument arg21 |
|
||||
unifiableMultiple01Aux0(k, t2, arg10, arg21) and
|
||||
unifiableMultiple01Aux1(k, t1, arg10, arg21)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate unifiableMultiple2Aux(
|
||||
CompoundTypeKind k, ConstructedGvnType t2, int i, GvnTypeArgument arg1, GvnTypeArgument arg2
|
||||
CompoundTypeKind k, ConstructedGvnType t2, int i, GvnTypeArgument arg1, boolean subsumes
|
||||
) {
|
||||
unifiableTypeArguments(k, arg1, arg2, i) and
|
||||
arg2 = getTypeArgument(k, t2, i) and
|
||||
i >= 2
|
||||
}
|
||||
|
||||
private predicate unifiableMultiple2(
|
||||
CompoundTypeKind k, ConstructedGvnType t1, ConstructedGvnType t2, int i
|
||||
) {
|
||||
exists(GvnTypeArgument arg1, GvnTypeArgument arg2 |
|
||||
unifiableMultiple2Aux(k, t2, i, arg1, arg2) and
|
||||
arg1 = getTypeArgument(k, t1, i)
|
||||
exists(GvnTypeArgument arg2 |
|
||||
unifiableTypeArguments(k, arg1, arg2, i, subsumes) and
|
||||
arg2 = getTypeArgument(k, t2, i) and
|
||||
i >= 2
|
||||
)
|
||||
}
|
||||
|
||||
@@ -452,43 +407,33 @@ module Gvn {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate unifiableMultiple(
|
||||
CompoundTypeKind k, ConstructedGvnType t1, ConstructedGvnType t2, int i
|
||||
CompoundTypeKind k, ConstructedGvnType t1, ConstructedGvnType t2, int i, boolean subsumes
|
||||
) {
|
||||
unifiableMultiple01(k, t1, t2) and i = 1
|
||||
exists(GvnTypeArgument arg10, GvnTypeArgument arg21, boolean subsumes1, boolean subsumes2 |
|
||||
unifiableMultiple01Aux0(k, t2, arg10, arg21, subsumes1) and
|
||||
unifiableMultiple01Aux1(k, t1, arg10, arg21, subsumes2) and
|
||||
subsumes = subsumes1.booleanAnd(subsumes2)
|
||||
) and
|
||||
i = 1
|
||||
or
|
||||
unifiableMultiple(k, t1, t2, i - 1) and
|
||||
unifiableMultiple2(k, t1, t2, i)
|
||||
}
|
||||
|
||||
private newtype TTypePath =
|
||||
TTypePathNil() or
|
||||
TTypePathCons(int head, TTypePath tail) { exists(getTypeAtCons(_, head, tail)) }
|
||||
|
||||
/**
|
||||
* Gets the GVN inside GVN `t`, by following the path `path`, if any.
|
||||
*/
|
||||
private GvnType getTypeAt(GvnType t, TTypePath path) {
|
||||
path = TTypePathNil() and
|
||||
result = t
|
||||
or
|
||||
exists(ConstructedGvnTypeList l, int head, TTypePath tail |
|
||||
t = TConstructedGvnType(l) and
|
||||
path = TTypePathCons(head, tail) and
|
||||
result = getTypeAtCons(l, head, tail)
|
||||
exists(GvnTypeArgument arg1, boolean subsumes1, boolean subsumes2 |
|
||||
unifiableMultiple(k, t1, t2, i - 1, subsumes1) and
|
||||
unifiableMultiple2Aux(k, t2, i, arg1, subsumes2) and
|
||||
arg1 = getTypeArgument(k, t1, i) and
|
||||
subsumes = subsumes1.booleanAnd(subsumes2)
|
||||
)
|
||||
}
|
||||
|
||||
private GvnType getTypeAtCons(ConstructedGvnTypeList l, int head, TTypePath tail) {
|
||||
result = getTypeAt(l.getArg(head), tail)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the leaf GVN inside GVN `t`, by following the path `path`, if any.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private GvnType getLeafTypeAt(GvnType t, TTypePath path) {
|
||||
result = getTypeAt(t, path) and
|
||||
not result instanceof ConstructedGvnType
|
||||
pragma[nomagic]
|
||||
private predicate unifiable(ConstructedGvnType t1, ConstructedGvnType t2, boolean subsumes) {
|
||||
exists(CompoundTypeKind k, GvnTypeArgument arg1, GvnTypeArgument arg2 |
|
||||
unifiableSingle0(k, t2, arg1, arg2, subsumes) and
|
||||
arg1 = getTypeArgument(k, t1, 0)
|
||||
)
|
||||
or
|
||||
exists(CompoundTypeKind k |
|
||||
unifiableMultiple(k, t1, t2, k.getNumberOfTypeParameters() - 1, subsumes)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -540,33 +485,20 @@ module Gvn {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if GVNs `t1` and `t2` can be unified. That is, is it possible to
|
||||
* Holds if GVNs `t1` and `t2` can be unified. That is, it is possible to
|
||||
* replace all type parameters in `t1` and `t2` with some GVNs (possibly
|
||||
* type parameters themselves) to make the two substituted terms equal.
|
||||
*/
|
||||
cached
|
||||
predicate unifiable(ConstructedGvnType t1, ConstructedGvnType t2) {
|
||||
unifiableSingle(t1, t2)
|
||||
or
|
||||
exists(CompoundTypeKind k | unifiableMultiple(k, t1, t2, k.getNumberOfTypeParameters() - 1))
|
||||
}
|
||||
predicate unifiable(ConstructedGvnType t1, ConstructedGvnType t2) { unifiable(t1, t2, _) }
|
||||
|
||||
/**
|
||||
* Holds if GVN `t1` subsumes GVN `t2`. That is, is it possible to replace all
|
||||
* Holds if GVN `t1` subsumes GVN `t2`. That is, it is possible to replace all
|
||||
* type parameters in `t1` with some GVNs (possibly type parameters themselves)
|
||||
* to make the two substituted terms equal.
|
||||
*/
|
||||
cached
|
||||
predicate subsumes(ConstructedGvnType t1, ConstructedGvnType t2) {
|
||||
unifiable(t1, t2) and // subsumption implies unification
|
||||
forall(TTypePath path, GvnType leaf1 | leaf1 = getLeafTypeAt(t1, path) |
|
||||
exists(GvnType child2 | child2 = getTypeAt(t2, path) |
|
||||
leaf1 = TTypeParameterGvnType()
|
||||
or
|
||||
leaf1 = child2
|
||||
)
|
||||
)
|
||||
}
|
||||
predicate subsumes(ConstructedGvnType t1, ConstructedGvnType t2) { unifiable(t1, t2, true) }
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
@@ -88,6 +88,9 @@ private module Frameworks {
|
||||
private import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.security.dataflow.XSSSinks
|
||||
private import semmle.code.csharp.frameworks.ServiceStack
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.frameworks.EntityFramework
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3643,9 +3643,10 @@ private module Subpaths {
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, apout) and
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@ private import semmle.code.csharp.frameworks.system.data.Entity
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
|
||||
/**
|
||||
@@ -234,26 +235,29 @@ module EntityFramework {
|
||||
override Expr getSql() { result = this.getArgumentForParameter(sqlParam) }
|
||||
}
|
||||
|
||||
/** A call to `System.Data.Entity.DbSet.SqlQuery`. */
|
||||
class SystemDataEntityDbSetSqlExpr extends SqlExpr, MethodCall {
|
||||
SystemDataEntityDbSetSqlExpr() {
|
||||
this.getTarget() = any(SystemDataEntity::DbSet dbSet).getSqlQueryMethod()
|
||||
/** The sink method `System.Data.Entity.DbSet.SqlQuery`. */
|
||||
private class SystemDataEntityDbSetSqlQuerySinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
["System.Data.Entity;DbSet;false;SqlQuery;(System.String,System.Object[]);;Argument[0];sql"]
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgumentForName("sql") }
|
||||
}
|
||||
|
||||
/** A call to a method in `System.Data.Entity.Database` that executes SQL. */
|
||||
class SystemDataEntityDatabaseSqlExpr extends SqlExpr, MethodCall {
|
||||
SystemDataEntityDatabaseSqlExpr() {
|
||||
exists(SystemDataEntity::Database db |
|
||||
this.getTarget() = db.getSqlQueryMethod() or
|
||||
this.getTarget() = db.getExecuteSqlCommandMethod() or
|
||||
this.getTarget() = db.getExecuteSqlCommandAsyncMethod()
|
||||
)
|
||||
/** A sink method in `System.Data.Entity.Database` that executes SQL. */
|
||||
private class SystemDataEntityDatabaseSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"System.Data.Entity;Database;false;SqlQuery;(System.Type,System.String,System.Object[]);;Argument[1];sql",
|
||||
"System.Data.Entity;Database;false;SqlQuery<>;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommand;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Threading.CancellationToken,System.Object[]);;Argument[1];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Threading.CancellationToken,System.Object[]);;Argument[0];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"System.Data.Entity;Database;false;ExecuteSqlCommandAsync;(System.Data.Entity.TransactionalBehavior,System.String,System.Object[]);;Argument[1];sql"
|
||||
]
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgumentForName("sql") }
|
||||
}
|
||||
|
||||
/** Holds if `t` is compatible with a DB column type. */
|
||||
|
||||
321
csharp/ql/lib/semmle/code/csharp/frameworks/ServiceStack.qll
Normal file
321
csharp/ql/lib/semmle/code/csharp/frameworks/ServiceStack.qll
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* General modelling of ServiceStack framework including separate modules for:
|
||||
* - flow sources
|
||||
* - SQLi sinks
|
||||
* - XSS sinks
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** A class representing a Service */
|
||||
private class ServiceClass extends Class {
|
||||
ServiceClass() {
|
||||
this.getBaseClass+().hasQualifiedName("ServiceStack", "Service") or
|
||||
this.getABaseType*().getABaseInterface().hasQualifiedName("ServiceStack", "IService")
|
||||
}
|
||||
|
||||
/** Get a method that handles incoming requests */
|
||||
Method getARequestMethod() {
|
||||
exists(string name |
|
||||
result = this.getAMethod(name) and
|
||||
name.regexpMatch("(Get|Post|Put|Delete|Any|Option|Head|Patch)(Async|Json|Xml|Jsv|Csv|Html|Protobuf|Msgpack|Wire)?")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Top-level Request DTO types */
|
||||
private class RequestDTO extends Class {
|
||||
RequestDTO() {
|
||||
this.getABaseType*().getABaseInterface().hasQualifiedName("ServiceStack", "IReturn")
|
||||
}
|
||||
}
|
||||
|
||||
/** Flow sources for the ServiceStack framework */
|
||||
module Sources {
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
|
||||
/**
|
||||
* Remote flow sources for ServiceStack. Parameters of well-known `request` methods.
|
||||
*/
|
||||
private class ServiceStackSource extends RemoteFlowSource {
|
||||
ServiceStackSource() {
|
||||
exists(ServiceClass service |
|
||||
service.getARequestMethod().getAParameter() = this.asParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ServiceStack request parameter" }
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceStackRemoteSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// IRestClient
|
||||
"ServiceStack;IRestClient;true;Send<>;(System.String,System.String,System.Object);;Argument[2];remote",
|
||||
"ServiceStack;IRestClient;true;Patch<>;(System.String,System.Object);;Argument[1];remote",
|
||||
"ServiceStack;IRestClient;true;Post<>;(System.String,System.Object);;Argument[1];remote",
|
||||
"ServiceStack;IRestClient;true;Put<>;(System.String,System.Object);;Argument[1];remote",
|
||||
// IRestClientSync
|
||||
"ServiceStack;IRestClientSync;true;CustomMethod;(System.String,ServiceStack.IReturnVoid);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientSync;true;CustomMethod<>;(System.String,System.Object);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientSync;true;CustomMethod<>;(System.String,ServiceStack.IReturn<TResponse>);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientSync;true;Delete;(ServiceStack.IReturnVoid);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Delete<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Delete<>;(ServiceStack.IReturn<TResponse>);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Get;(ServiceStack.IReturnVoid);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Get<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Get<>;(ServiceStack.IReturn<TResponse>);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Patch;(ServiceStack.IReturnVoid);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Patch<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Patch<>;(ServiceStack.IReturn<TResponse>);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Post;(ServiceStack.IReturnVoid);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Post<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Post<>;(ServiceStack.IReturn<TResponse>);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Put;(ServiceStack.IReturnVoid);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Put<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientSync;true;Put<>;(ServiceStack.IReturn<TResponse>);;Argument[0];remote",
|
||||
// IRestGateway
|
||||
"ServiceStack;IRestGateway;true;Delete<>;(ServiceStack.IReturn<T>);;Argument[0];remote",
|
||||
"ServiceStack;IRestGateway;true;Get<>;(ServiceStack.IReturn<T>);;Argument[0];remote",
|
||||
"ServiceStack;IRestGateway;true;Post<>;(ServiceStack.IReturn<T>);;Argument[0];remote",
|
||||
"ServiceStack;IRestGateway;true;Put<>;(ServiceStack.IReturn<T>);;Argument[0];remote",
|
||||
"ServiceStack;IRestGateway;true;Send<>;(ServiceStack.IReturn<T>);;Argument[0];remote",
|
||||
// IOneWayClient
|
||||
"ServiceStack;IOneWayClient;true;SendAllOneWay;(System.Collections.Generic.IEnumerable<System.Object>);;Element of Argument[1];remote",
|
||||
"ServiceStack;IOneWayClient;true;SendOneWay;(System.String,System.Object);;Argument[1];remote",
|
||||
"ServiceStack;IOneWayClient;true;SendOneWay;(System.Object);;Argument[0];remote",
|
||||
// IServiceGateway
|
||||
"ServiceStack;IServiceGateway;true;Publish;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IServiceGateway;true;PublishAll;(System.Collections.Generic.IEnumerable<System.Object>);;Element of Argument[0];remote",
|
||||
"ServiceStack;IServiceGateway;true;Send<>;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;IServiceGateway;true;SendAll<>;(System.Collections.Generic.IEnumerable<System.Object>);;Element of Argument[0];remote",
|
||||
// IRestClientAsync
|
||||
"ServiceStack;IRestClientAsync;true;CustomMethodAsync;(System.String,ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientAsync;true;CustomMethodAsync<>;(System.String,System.Object,System.Threading.CancellationToken);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientAsync;true;CustomMethodAsync<>;(System.String,ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[1];remote",
|
||||
"ServiceStack;IRestClientAsync;true;DeleteAsync;(ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;DeleteAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;DeleteAsync<>;(ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;GetAsync;(ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;GetAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;GetAsync<>;(ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PatchAsync;(ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PatchAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PatchAsync<>;(ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PostAsync;(ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PostAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PostAsync<>;(ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PutAsync;(ServiceStack.IReturnVoid,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PutAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestClientAsync;true;PutAsync<>;(ServiceStack.IReturn<TResponse>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
// IRestGatewayAsync
|
||||
"ServiceStack;IRestGatewayAsync;true;DeleteAsync<>;(ServiceStack.IReturn<T>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestGatewayAsync;true;GetAsync<>;(ServiceStack.IReturn<T>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestGatewayAsync;true;PostAsync<>;(ServiceStack.IReturn<T>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestGatewayAsync;true;PutAsync<>;(ServiceStack.IReturn<T>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IRestGatewayAsync;true;SendAsync<>;(ServiceStack.IReturn<T>,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
// IServiceGatewayAsync
|
||||
"ServiceStack;IServiceGatewayAsync;true;PublishAsync;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IServiceGatewayAsync;true;PublishAllAsync;(System.Collections.Generic.IEnumerable<System.Object>,System.Threading.CancellationToken);;Element of Argument[0];remote",
|
||||
"ServiceStack;IServiceGatewayAsync;true;SendAsync<>;(System.Object,System.Threading.CancellationToken);;Argument[0];remote",
|
||||
"ServiceStack;IServiceGatewayAsync;true;SendAllAsync<>;(System.Collections.Generic.IEnumerable<System.Object>,System.Threading.CancellationToken);;Element of Argument[0];remote",
|
||||
// ServiceClientBase
|
||||
"ServiceStack;ServiceClientBase;true;Publish<>;(T);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Publish<>;(ServiceStack.Messaging.IMessage<T>);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Delete;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Get;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Patch;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Post;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Put;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Head;(System.Object);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;Head;(ServiceStack.IReturn);;Argument[0];remote",
|
||||
"ServiceStack;ServiceClientBase;true;CustomMethod;(System.String,System.String,System.Object);;Argument[2];remote",
|
||||
"ServiceStack;ServiceClientBase;true;CustomMethod<>;(System.String,System.String,System.Object);;Argument[2];remote",
|
||||
"ServiceStack;ServiceClientBase;true;CustomMethodAsync<>;(System.String,System.String,System.Object,System.Threading.CancellationToken);;Argument[2];remote",
|
||||
"ServiceStack;ServiceClientBase;true;DownloadBytes;(System.String,System.String,System.Object);;Argument[2];remote",
|
||||
"ServiceStack;ServiceClientBase;true;DownloadBytesAsync;(System.String,System.String,System.Object);;Argument[2];remote"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceStackSqlSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// SqlExpression<T>
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeAnd;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeFrom;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeGroupBy;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeHaving;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeOr;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeOrderBy;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeSelect;(System.String,System.Boolean);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeSelect;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;SqlExpression<>;true;UnsafeWhere;(System.String,System.Object[]);;Argument[0];sql",
|
||||
// IUntypedSqlExpression
|
||||
"ServiceStack.OrmLite;IUntypedSqlExpression;true;UnsafeAnd;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;IUntypedSqlExpression;true;UnsafeFrom;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;IUntypedSqlExpression;true;UnsafeOr;(System.String,System.Object[]);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;IUntypedSqlExpression;true;UnsafeSelect;(System.String);;Argument[0];sql",
|
||||
"ServiceStack.OrmLite;IUntypedSqlExpression;true;UnsafeWhere;(System.String,System.Object[]);;Argument[0];sql",
|
||||
// OrmLiteReadApi
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ExecuteNonQuery;(System.Data.IDbConnection,System.String);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ExecuteNonQuery;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ExecuteNonQuery;(System.Data.IDbConnection,System.String,System.Action<System.Data.IDbCommand>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ExecuteNonQuery;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Exists<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Dictionary<,>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Lookup<,>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Lookup<,>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;KeyValuePairs;(System.Data.IDbConnection,System.String,System.System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Scalar<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Scalar<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Select<>;(System.Data.IDbConnection,System.Type,System.String,System.Object);;Argument[2];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Select<>;(System.Data.IDbConnection,System.String);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Select<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Select<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Select<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SelectLazy<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SelectNonDefaults<>;(System.Data.IDbConnection,System.String,T);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Single<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Single<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlColumn<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlColumn<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlColumn<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlList<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlList<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlList<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlList<>;(System.Data.IDbConnection,System.String,System.Action<System.Data.IDbCommand>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlScalar<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlScalar<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;SqlScalar<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Column<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;Column<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ColumnDistinct<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ColumnDistinct<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ColumnLazy<>;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApi;false;ColumnLazy<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
// OrmLiteReadExpressionsApi
|
||||
"ServiceStack.OrmLite;OrmLiteReadExpressionsApi;false;RowCount;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadExpressionsApi;false;RowCount;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>);;Argument[1];sql",
|
||||
// OrmLiteReadExpressionsApiAsync
|
||||
"ServiceStack.OrmLite;OrmLiteReadExpressionsApiAsync;false;RowCountAsync;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
// OrmLiteReadApiAsync
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ColumnAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ColumnAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ColumnDistinctAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ColumnDistinctAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;DictionaryAsync<,>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ExecuteNonQueryAsync;(System.Data.IDbConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ExecuteNonQueryAsync;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ExecuteNonQueryAsync;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ExistsAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;KeyValuePairsAsync<,>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;KeyValuePairsAsync<,>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;LookupAsync<,>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;LookupAsync<,>;(System.Data.IDbCommand,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;LookupAsync<,>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ScalarAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;ScalarAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectAsync<>;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Threading.CancellationToken);;Argument[2];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectAsync<>;(System.Data.IDbConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SelectNonDefaultsAsync<>;(System.Data.IDbConnection,System.String,T,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SingleAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SingleAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlColumnAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlColumnAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlColumnAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlListAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlListAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlListAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlListAsync<>;(System.Data.IDbConnection,System.String,System.Action<System.Data.IDbCommand>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlScalarAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlScalarAsync<>;(System.Data.IDbConnection,System.String,System.Collections.Generic.IEnumerable<System.Data.IDbDataParameter>,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteReadApiAsync;false;SqlScalarAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
// Write API
|
||||
"ServiceStack.OrmLite;OrmLiteWriteApi;false;ExecuteSql;(System.Data.IDbConnection,System.String);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteWriteApi;false;ExecuteSql;(System.Data.IDbConnection,System.String,System.Object);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteWriteApi;false;ExecuteSql;(System.Data.IDbConnection,System.String,System.Collections.Generic.Dictionary<System.String,System.Object>);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteWriteApiAsync;false;ExecuteSqlAsync;(System.Data.IDbConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"ServiceStack.OrmLite;OrmLiteWriteApiAsync;false;ExecuteSqlAsync;(System.Data.IDbConnection,System.String,System.Object,System.Threading.CancellationToken);;Argument[1];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceStackCodeInjectionSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// Redis API
|
||||
"ServiceStack.Redis;IRedisClient;true;Custom;(System.Object[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecCachedLua;(System.String,System.Func<System.String,T>);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLua;(System.String,System.String[],System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLua;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsInt;(System.String,System.String[],System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsInt;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsList;(System.String,System.String[],System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsList;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsString;(System.String,System.String[],System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;ExecLuaAsString;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClient;true;LoadLuaScript;(System.String);;Argument[0];code",
|
||||
// IRedisClientAsync
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;CustomAsync;(System.Object[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;CustomAsync;(System.Object[],System.Threading.CancellationToken);;Element of Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecCachedLuaAsync;(System.String,System.Func<System.String,System.Threading.Tasks.ValueTask<T>>,System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsync;(System.String,System.String[],System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsync;(System.String,System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsync;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsIntAsync;(System.String,System.String[],System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsIntAsync;(System.String,System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsIntAsync;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsStringAsync;(System.String,System.String[],System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsStringAsync;(System.String,System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsStringAsync;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsListAsync;(System.String,System.String[],System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsListAsync;(System.String,System.String[],System.Threading.CancellationToken);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;ExecLuaAsListAsync;(System.String,System.String[]);;Argument[0];code",
|
||||
"ServiceStack.Redis;IRedisClientAsync;true;LoadLuaScriptAsync;(System.String,System.Threading.CancellationToken);;Argument[0];code"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceStackXssSummaryModelCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.String,System.String);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.Object,System.String,System.Net.HttpStatusCode);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.Object,System.String);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.Object,System.Net.HttpStatusCode);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.Object);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.IO.Stream,System.String);;Argument[0];ReturnValue;taint",
|
||||
"ServiceStack;HttpResult;false;HttpResult;(System.Byte[],System.String);;Argument[0];ReturnValue;taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** XSS support for ServiceStack framework */
|
||||
module XSS {
|
||||
private import semmle.code.csharp.security.dataflow.XSSSinks
|
||||
|
||||
/** XSS sinks for ServiceStack */
|
||||
class XssSink extends Sink {
|
||||
XssSink() {
|
||||
exists(ServiceClass service, Method m, Expr e |
|
||||
service.getARequestMethod() = m and
|
||||
this.asExpr() = e and
|
||||
m.canReturn(e) and
|
||||
(
|
||||
e.getType() instanceof StringType or
|
||||
e.getType().hasQualifiedName("ServiceStack", "HttpResult")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ private import semmle.code.csharp.frameworks.EntityFramework
|
||||
private import semmle.code.csharp.frameworks.NHibernate
|
||||
private import semmle.code.csharp.frameworks.Dapper
|
||||
private import semmle.code.csharp.dataflow.DataFlow4
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** An expression containing a SQL command. */
|
||||
abstract class SqlExpr extends Expr {
|
||||
@@ -28,71 +29,236 @@ class CommandTextAssignmentSqlExpr extends SqlExpr, AssignExpr {
|
||||
override Expr getSql() { result = this.getRValue() }
|
||||
}
|
||||
|
||||
/** A construction of an `IDbCommand` object. */
|
||||
/** A construction of an unknown `IDbCommand` object. */
|
||||
class IDbCommandConstructionSqlExpr extends SqlExpr, ObjectCreation {
|
||||
IDbCommandConstructionSqlExpr() {
|
||||
exists(InstanceConstructor ic | ic = this.getTarget() |
|
||||
ic.getDeclaringType().getABaseType*() instanceof SystemDataIDbCommandInterface and
|
||||
ic.getParameter(0).getType() instanceof StringType
|
||||
ic.getParameter(0).getType() instanceof StringType and
|
||||
not ic.getDeclaringType()
|
||||
.hasQualifiedName([
|
||||
// Known sealed classes:
|
||||
"System.Data.SqlClient.SqlCommand", "System.Data.Odbc.OdbcCommand",
|
||||
"System.Data.OleDb.OleDbCommand", "System.Data.EntityClient.EntityCommand"
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** A construction of a known `IDbCommand` object. */
|
||||
private class IDbCommandConstructionSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// SqlCommand
|
||||
"System.Data.SqlClient;SqlCommand;false;SqlCommand;(System.String);;Argument[0];sql",
|
||||
"System.Data.SqlClient;SqlCommand;false;SqlCommand;(System.String,System.Data.SqlClient.SqlConnection);;Argument[0];sql",
|
||||
"System.Data.SqlClient;SqlCommand;false;SqlCommand;(System.String,System.Data.SqlClient.SqlConnection,System.Data.SqlClient.SqlTransaction);;Argument[0];sql",
|
||||
// OdbcCommand
|
||||
"System.Data.Odbc;OdbcCommand;false;OdbcCommand;(System.String);;Argument[0];sql",
|
||||
"System.Data.Odbc;OdbcCommand;false;OdbcCommand;(System.String,System.Data.Odbc.OdbcConnection);;Argument[0];sql",
|
||||
"System.Data.Odbc;OdbcCommand;false;OdbcCommand;(System.String,System.Data.Odbc.OdbcConnection,System.Data.Odbc.OdbcTransaction);;Argument[0];sql",
|
||||
// OleDbCommand
|
||||
"System.Data.OleDb;OleDbCommand;false;OleDbCommand;(System.String);;Argument[0];sql",
|
||||
"System.Data.OleDb;OleDbCommand;false;OleDbCommand;(System.String,System.Data.OleDb.OleDbConnection);;Argument[0];sql",
|
||||
"System.Data.OleDb;OleDbCommand;false;OleDbCommand;(System.String,System.Data.OleDb.OleDbConnection,System.Data.OleDb.OleDbTransaction);;Argument[0];sql",
|
||||
// EntityCommand
|
||||
"System.Data.EntityClient;EntityCommand;false;EntityCommand;(System.String);;Argument[0];sql",
|
||||
"System.Data.EntityClient;EntityCommand;false;EntityCommand;(System.String,System.Data.EntityClient.EntityConnection);;Argument[0];sql",
|
||||
"System.Data.EntityClient;EntityCommand;false;EntityCommand;(System.String,System.Data.EntityClient.EntityConnection,System.Data.EntityClient.EntityTransaction);;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** A construction of an `SqlDataAdapter` object. */
|
||||
class SqlDataAdapterConstructionSqlExpr extends SqlExpr, ObjectCreation {
|
||||
SqlDataAdapterConstructionSqlExpr() {
|
||||
exists(InstanceConstructor ic |
|
||||
ic = this.getTarget() and
|
||||
ic.getDeclaringType() instanceof SystemDataSqlClientSqlDataAdapterClass and
|
||||
ic.getParameter(0).getType() instanceof StringType
|
||||
)
|
||||
private class SqlDataAdapterConstructionSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"System.Data.SqlClient;SqlDataAdapter;false;SqlDataAdapter;(System.String,System.String);;Argument[0];sql",
|
||||
"System.Data.SqlClient;SqlDataAdapter;false;SqlDataAdapter;(System.String,System.Data.SqlClient.SqlConnection);;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** A `MySql.Data.MySqlClient.MySqlHelper` method. */
|
||||
class MySqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall {
|
||||
MySqlHelperMethodCallSqlExpr() {
|
||||
this.getQualifier().getType().(Class).hasQualifiedName("MySql.Data.MySqlClient", "MySqlHelper")
|
||||
}
|
||||
|
||||
override Expr getSql() {
|
||||
exists(int i |
|
||||
result = getArgument(i) and
|
||||
this.getTarget().getParameter(i).hasName("commandText") and
|
||||
this.getTarget().getParameter(i).getType() instanceof StringType
|
||||
)
|
||||
private class MySqlHelperMethodCallSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// ExecuteDataRow/Async
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataRow;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataRowAsync;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataRowAsync;(System.String,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteDataset
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataset;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataset;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataset;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDataset;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteDatasetAsync
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(System.String,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(System.String,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteDatasetAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteNonQuery
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQuery;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQuery;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteNonQueryAsync
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQueryAsync;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQueryAsync;(System.String,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQueryAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteNonQueryAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteReader
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReader;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReader;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReader;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReader;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteReaderAsync
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(System.String,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(System.String,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteReaderAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteScalar
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalar;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalar;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalar;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalar;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// ExecuteScalarAsync
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(System.String,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(System.String,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(System.String,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(System.String,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;ExecuteScalarAsync;(MySql.Data.MySqlClient.MySqlConnection,System.String,System.Threading.CancellationToken,MySql.Data.MySqlClient.MySqlParameter[]);;Argument[1];sql",
|
||||
// UpdateDataset/Async
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;UpdateDataset;(System.String,System.String,System.Data.DataSet,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;UpdateDatasetAsync;(System.String,System.String,System.Data.DataSet,System.String);;Argument[1];sql",
|
||||
"MySql.Data.MySqlClient;MySqlHelper;false;UpdateDatasetAsync;(System.String,System.String,System.Data.DataSet,System.String,System.Threading.CancellationToken);;Argument[1];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Microsoft.ApplicationBlocks.Data.SqlHelper` method. */
|
||||
class MicrosoftSqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall {
|
||||
MicrosoftSqlHelperMethodCallSqlExpr() {
|
||||
this.getQualifier()
|
||||
.getType()
|
||||
.(Class)
|
||||
.hasQualifiedName("Microsoft.ApplicationBlocks.Data", "SqlHelper")
|
||||
}
|
||||
|
||||
override Expr getSql() {
|
||||
exists(int i |
|
||||
result = getArgument(i) and
|
||||
this.getTarget().getParameter(i).hasName("commandText") and
|
||||
this.getTarget().getParameter(i).getType() instanceof StringType
|
||||
)
|
||||
private class MicrosoftSqlHelperSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// ExecuteNonQuery
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.String,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.String,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteNonQuery;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
// ExecuteDataset
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.String,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.String,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteDataset;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
// ExecuteReader
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.String,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.String,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteReader;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
// ExecuteScalar
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.String,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.String,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteScalar;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
// ExecuteXmlReader
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteXmlReader;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteXmlReader;(System.Data.SqlClient.SqlConnection,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteXmlReader;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String);;Argument[2];sql",
|
||||
"Microsoft.ApplicationBlocks.Data;SqlHelper;false;ExecuteXmlReader;(System.Data.SqlClient.SqlTransaction,System.Data.CommandType,System.String,System.Data.SqlClient.SqlParameter[]);;Argument[2];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Dapper.SqlMapper` method that is taking a SQL string argument. */
|
||||
class DapperSqlMethodCallSqlExpr extends SqlExpr, MethodCall {
|
||||
DapperSqlMethodCallSqlExpr() {
|
||||
this.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod()
|
||||
private class DapperSqlMapperSinkModelCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// Execute*
|
||||
"Dapper;SqlMapper;false;Execute;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteScalar;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteScalarAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteScalar<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteScalarAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteReader;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;ExecuteReaderAsync;(System.Data.DbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
// Query*
|
||||
"Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryMultiple;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryMultipleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirst<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefault<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefaultAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingle<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefault<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefaultAsync<>;(System.Data.IDbConnection,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
// Query* with System.Type parameter
|
||||
"Dapper;SqlMapper;false;Query;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Boolean,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirst;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QueryFirstOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingle;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefault;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
"Dapper;SqlMapper;false;QuerySingleOrDefaultAsync;(System.Data.IDbConnection,System.Type,System.String,System.Object,System.Data.IDbTransaction,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[2];sql",
|
||||
// Query with multiple type parameters
|
||||
"Dapper;SqlMapper;false;Query<,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<,,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;Query<,,,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<,,,,,,,>;(System.Data.IDbConnection,System.String,System.Func<TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
// Query with System.Type[] parameter
|
||||
"Dapper;SqlMapper;false;Query<>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql",
|
||||
"Dapper;SqlMapper;false;QueryAsync<>;(System.Data.IDbConnection,System.String,System.Type[],System.Func<System.Object[],TReturn>,System.Object,System.Data.IDbTransaction,System.Boolean,System.String,System.Nullable<System.Int32>,System.Nullable<System.Data.CommandType>);;Argument[1];sql"
|
||||
]
|
||||
}
|
||||
|
||||
override Expr getSql() { result = this.getArgumentForName("sql") }
|
||||
}
|
||||
|
||||
/** A `Dapper.CommandDefinition` creation that is taking a SQL string argument and is passed to a `Dapper.SqlMapper` method. */
|
||||
|
||||
@@ -7,6 +7,7 @@ private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
private import semmle.code.csharp.frameworks.system.codedom.Compiler
|
||||
private import semmle.code.csharp.security.Sanitizers
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A data flow source for user input treated as code vulnerabilities.
|
||||
@@ -79,3 +80,8 @@ class RoslynCSharpScriptSink extends Sink {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Code injection sinks defined through CSV models. */
|
||||
private class ExternalCodeInjectionExprSink extends Sink {
|
||||
ExternalCodeInjectionExprSink() { sinkNode(this, "code") }
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.security.Sanitizers
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A source specific to SQL injection vulnerabilities.
|
||||
@@ -51,6 +52,11 @@ class SqlInjectionExprSink extends Sink {
|
||||
SqlInjectionExprSink() { exists(SqlExpr s | this.getExpr() = s.getSql()) }
|
||||
}
|
||||
|
||||
/** SQL sinks defined through CSV models. */
|
||||
private class ExternalSqlInjectionExprSink extends Sink {
|
||||
ExternalSqlInjectionExprSink() { sinkNode(this, "sql") }
|
||||
}
|
||||
|
||||
private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { }
|
||||
|
||||
private class GuidSanitizer extends Sanitizer, GuidSanitizedExpr { }
|
||||
|
||||
@@ -62,6 +62,16 @@ module PathGraph {
|
||||
key = "semmle.label" and
|
||||
val = n.(XssAspNode).toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
query predicate subpaths(XssNode arg, XssNode par, XssNode ret, XssNode out) {
|
||||
DataFlow2::PathGraph::subpaths(arg.asDataFlowNode(), par.asDataFlowNode(), ret.asDataFlowNode(),
|
||||
out.asDataFlowNode())
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TXssNode =
|
||||
|
||||
@@ -10,6 +10,7 @@ private import semmle.code.csharp.frameworks.system.web.UI
|
||||
private import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
private import semmle.code.csharp.security.dataflow.flowsinks.Remote
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.frameworks.ServiceStack::XSS
|
||||
|
||||
/**
|
||||
* A data flow sink for cross-site scripting (XSS) vulnerabilities.
|
||||
|
||||
@@ -6,6 +6,7 @@ import csharp
|
||||
private import Remote
|
||||
private import semmle.code.csharp.commons.Loggers
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* An external location sink.
|
||||
@@ -16,6 +17,10 @@ private import semmle.code.csharp.frameworks.system.Web
|
||||
*/
|
||||
abstract class ExternalLocationSink extends DataFlow::ExprNode { }
|
||||
|
||||
private class ExternalModelSink extends ExternalLocationSink {
|
||||
ExternalModelSink() { sinkNode(this, "remote") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to a call to a method on a logger class.
|
||||
*/
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -32,21 +32,21 @@ edges
|
||||
| Types.cs:74:9:74:9 | access to local variable d : D | Types.cs:16:30:16:30 | this : D |
|
||||
| Types.cs:77:22:77:22 | a : C | Types.cs:79:18:79:25 | SSA def(b) : C |
|
||||
| Types.cs:79:18:79:25 | SSA def(b) : C | Types.cs:80:18:80:18 | access to local variable b |
|
||||
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [field Field] : Types.E<D>.E2 | Types.cs:93:13:93:16 | this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | Types.cs:92:13:92:16 | [post] this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [field Field] : Types.E<D>.E2 | Types.cs:113:34:113:34 | this [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:90:22:90:22 | e : Types.E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [field Field] : Types.E<D>.E2 | Types.cs:115:22:115:25 | this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [field Field] : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field |
|
||||
| Types.cs:90:22:90:22 | e : Types+E<D>.E2 | Types.cs:92:26:92:26 | access to parameter e : Types+E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [field Field] : Types+E<D>.E2 | Types.cs:93:13:93:16 | this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types+E<D>.E2 | Types.cs:92:13:92:16 | [post] this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [field Field] : Types+E<D>.E2 | Types.cs:113:34:113:34 | this [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types+E<D>.E2 | Types.cs:90:22:90:22 | e : Types+E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [field Field] : Types+E<D>.E2 | Types.cs:115:22:115:25 | this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [field Field] : Types+E<D>.E2 | Types.cs:115:22:115:31 | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:30:122:30 | access to local variable a : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types+E<D>.E2 | Types.cs:123:30:123:31 | access to local variable e2 : Types+E<D>.E2 |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:122:22:122:31 | call to method Through |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:130:34:130:34 | x : A |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | Types.cs:130:34:130:34 | x : Types.E<D>.E2 |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types+E<D>.E2 | Types.cs:123:22:123:32 | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types+E<D>.E2 | Types.cs:130:34:130:34 | x : Types+E<D>.E2 |
|
||||
| Types.cs:130:34:130:34 | x : A | Types.cs:130:40:130:40 | access to parameter x : A |
|
||||
| Types.cs:130:34:130:34 | x : Types.E<D>.E2 | Types.cs:130:40:130:40 | access to parameter x : Types.E<D>.E2 |
|
||||
| Types.cs:130:34:130:34 | x : Types+E<D>.E2 | Types.cs:130:40:130:40 | access to parameter x : Types+E<D>.E2 |
|
||||
| Types.cs:138:21:138:25 | this [field Field] : Object | Types.cs:138:32:138:35 | this access [field Field] : Object |
|
||||
| Types.cs:138:32:138:35 | this access [field Field] : Object | Types.cs:153:30:153:30 | this [field Field] : Object |
|
||||
| Types.cs:144:13:144:13 | [post] access to parameter c [field Field] : Object | Types.cs:145:13:145:13 | access to parameter c [field Field] : Object |
|
||||
@@ -97,24 +97,24 @@ nodes
|
||||
| Types.cs:77:22:77:22 | a : C | semmle.label | a : C |
|
||||
| Types.cs:79:18:79:25 | SSA def(b) : C | semmle.label | SSA def(b) : C |
|
||||
| Types.cs:80:18:80:18 | access to local variable b | semmle.label | access to local variable b |
|
||||
| Types.cs:90:22:90:22 | e : Types.E<D>.E2 | semmle.label | e : Types.E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [field Field] : Types.E<D>.E2 | semmle.label | [post] this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types.E<D>.E2 | semmle.label | access to parameter e : Types.E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [field Field] : Types.E<D>.E2 | semmle.label | this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [field Field] : Types.E<D>.E2 | semmle.label | this [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [field Field] : Types.E<D>.E2 | semmle.label | this access [field Field] : Types.E<D>.E2 |
|
||||
| Types.cs:90:22:90:22 | e : Types+E<D>.E2 | semmle.label | e : Types+E<D>.E2 |
|
||||
| Types.cs:92:13:92:16 | [post] this access [field Field] : Types+E<D>.E2 | semmle.label | [post] this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:92:26:92:26 | access to parameter e : Types+E<D>.E2 | semmle.label | access to parameter e : Types+E<D>.E2 |
|
||||
| Types.cs:93:13:93:16 | this access [field Field] : Types+E<D>.E2 | semmle.label | this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types+E<D>.E2 | semmle.label | object creation of type E2 : Types+E<D>.E2 |
|
||||
| Types.cs:113:34:113:34 | this [field Field] : Types+E<D>.E2 | semmle.label | this [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:115:22:115:25 | this access [field Field] : Types+E<D>.E2 | semmle.label | this access [field Field] : Types+E<D>.E2 |
|
||||
| Types.cs:115:22:115:31 | access to field Field | semmle.label | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | semmle.label | object creation of type A : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | semmle.label | object creation of type E2 : Types.E<D>.E2 |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types+E<D>.E2 | semmle.label | object creation of type E2 : Types+E<D>.E2 |
|
||||
| Types.cs:122:22:122:31 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | semmle.label | access to local variable a : A |
|
||||
| Types.cs:123:22:123:32 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | semmle.label | access to local variable e2 : Types.E<D>.E2 |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types+E<D>.E2 | semmle.label | access to local variable e2 : Types+E<D>.E2 |
|
||||
| Types.cs:130:34:130:34 | x : A | semmle.label | x : A |
|
||||
| Types.cs:130:34:130:34 | x : Types.E<D>.E2 | semmle.label | x : Types.E<D>.E2 |
|
||||
| Types.cs:130:34:130:34 | x : Types+E<D>.E2 | semmle.label | x : Types+E<D>.E2 |
|
||||
| Types.cs:130:40:130:40 | access to parameter x : A | semmle.label | access to parameter x : A |
|
||||
| Types.cs:130:40:130:40 | access to parameter x : Types.E<D>.E2 | semmle.label | access to parameter x : Types.E<D>.E2 |
|
||||
| Types.cs:130:40:130:40 | access to parameter x : Types+E<D>.E2 | semmle.label | access to parameter x : Types+E<D>.E2 |
|
||||
| Types.cs:138:21:138:25 | this [field Field] : Object | semmle.label | this [field Field] : Object |
|
||||
| Types.cs:138:32:138:35 | this access [field Field] : Object | semmle.label | this access [field Field] : Object |
|
||||
| Types.cs:144:13:144:13 | [post] access to parameter c [field Field] : Object | semmle.label | [post] access to parameter c [field Field] : Object |
|
||||
@@ -125,7 +125,7 @@ nodes
|
||||
| Types.cs:153:42:153:51 | access to field Field | semmle.label | access to field Field |
|
||||
subpaths
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:130:34:130:34 | x : A | Types.cs:130:40:130:40 | access to parameter x : A | Types.cs:122:22:122:31 | call to method Through : A |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types.E<D>.E2 | Types.cs:130:34:130:34 | x : Types.E<D>.E2 | Types.cs:130:40:130:40 | access to parameter x : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through : Types.E<D>.E2 |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : Types+E<D>.E2 | Types.cs:130:34:130:34 | x : Types+E<D>.E2 | Types.cs:130:40:130:40 | access to parameter x : Types+E<D>.E2 | Types.cs:123:22:123:32 | call to method Through : Types+E<D>.E2 |
|
||||
#select
|
||||
| Types.cs:23:12:23:18 | object creation of type C : C | Types.cs:23:12:23:18 | object creation of type C : C | Types.cs:50:18:50:18 | access to local variable c | $@ | Types.cs:50:18:50:18 | access to local variable c | access to local variable c |
|
||||
| Types.cs:25:12:25:18 | object creation of type C : C | Types.cs:25:12:25:18 | object creation of type C : C | Types.cs:63:33:63:36 | (...) ... | $@ | Types.cs:63:33:63:36 | (...) ... | (...) ... |
|
||||
@@ -141,7 +141,7 @@ subpaths
|
||||
| Types.cs:39:12:39:18 | object creation of type D : D | Types.cs:39:12:39:18 | object creation of type D : D | Types.cs:69:52:69:52 | access to parameter x | $@ | Types.cs:69:52:69:52 | access to parameter x | access to parameter x |
|
||||
| Types.cs:40:12:40:18 | object creation of type D : D | Types.cs:40:12:40:18 | object creation of type D : D | Types.cs:16:42:16:45 | this access | $@ | Types.cs:16:42:16:45 | this access | this access |
|
||||
| Types.cs:43:20:43:23 | null : null | Types.cs:43:20:43:23 | null : null | Types.cs:44:14:44:14 | access to local variable o | $@ | Types.cs:44:14:44:14 | access to local variable o | access to local variable o |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:110:25:110:32 | object creation of type E2 : Types.E<D>.E2 | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : Types+E<D>.E2 | Types.cs:110:25:110:32 | object creation of type E2 : Types+E<D>.E2 | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:22:122:31 | call to method Through | $@ | Types.cs:122:22:122:31 | call to method Through | call to method Through |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:121:26:121:33 | object creation of type E2 : Types.E<D>.E2 | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : Types+E<D>.E2 | Types.cs:121:26:121:33 | object creation of type E2 : Types+E<D>.E2 | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
|
||||
| Types.cs:144:23:144:34 | object creation of type Object : Object | Types.cs:144:23:144:34 | object creation of type Object : Object | Types.cs:153:42:153:51 | access to field Field | $@ | Types.cs:153:42:153:51 | access to field Field | access to field Field |
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ServiceStack;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using System.IO;
|
||||
|
||||
namespace ServiceStackTest
|
||||
{
|
||||
public class ResponseDto { }
|
||||
public class ReqDto1 : IReturn<ResponseDto> { }
|
||||
|
||||
public class ReqDto2 : IReturnVoid { }
|
||||
|
||||
public class C
|
||||
{
|
||||
public async Task M()
|
||||
{
|
||||
var client = new JsonServiceClient("");
|
||||
|
||||
client.DeserializeFromStream<object>(new MemoryStream()); // not a sink
|
||||
|
||||
client.Get(new ReqDto1());
|
||||
client.Get(new ReqDto2());
|
||||
client.Get<ResponseDto>("relativeOrAbsoluteUrl"); // not a sink
|
||||
client.Get<ResponseDto>(new object());
|
||||
client.Get("relativeOrAbsoluteUrl"); // not a sink
|
||||
client.Get(new object());
|
||||
|
||||
await client.GetAsync<ResponseDto>("relativeOrAbsoluteUrl"); // not a sink
|
||||
await client.GetAsync<ResponseDto>(new object());
|
||||
await client.GetAsync(new ReqDto1());
|
||||
await client.GetAsync(new ReqDto2());
|
||||
|
||||
|
||||
client.CustomMethod("GET", new ReqDto2());
|
||||
client.CustomMethod<ResponseDto>("GET", "relativeOrAbsoluteUrl", new ReqDto1());
|
||||
client.CustomMethod<ResponseDto>("GET", new ReqDto1());
|
||||
client.CustomMethod<ResponseDto>("GET", new object());
|
||||
client.CustomMethod("GET", "relativeOrAbsoluteUrl", new object());
|
||||
client.CustomMethod("GET", (IReturnVoid)null);
|
||||
await client.CustomMethodAsync("GET", new ReqDto2());
|
||||
await client.CustomMethodAsync<ResponseDto>("GET", "relativeOrAbsoluteUrl", new ReqDto1());
|
||||
await client.CustomMethodAsync<ResponseDto>("GET", new ReqDto1());
|
||||
await client.CustomMethodAsync<ResponseDto>("GET", new object());
|
||||
|
||||
client.DownloadBytes("GET", "requestUri", new object());
|
||||
await client.DownloadBytesAsync("GET", "relativeOrAbsoluteUrl", new object());
|
||||
|
||||
client.Head(new object());
|
||||
client.Patch(new object());
|
||||
client.Post(new object());
|
||||
client.Put(new object());
|
||||
|
||||
client.Send<ResponseDto>(new object());
|
||||
client.Publish(new ReqDto1());
|
||||
client.SendOneWay(new object());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ServiceStack;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using ServiceStack.OrmLite;
|
||||
|
||||
namespace ServiceStackTest
|
||||
{
|
||||
public class Table
|
||||
{
|
||||
public int Column { get; set; }
|
||||
}
|
||||
|
||||
public class Sql
|
||||
{
|
||||
public static async Task M()
|
||||
{
|
||||
ServiceStack.OrmLite.SqlExpression<int> expr = null;
|
||||
|
||||
expr = expr.Select<Table>(t => t.Column); // ok
|
||||
|
||||
expr = expr
|
||||
.UnsafeAnd("SQL")
|
||||
.UnsafeFrom("SQL")
|
||||
.UnsafeGroupBy("SQL")
|
||||
.UnsafeHaving("SQL")
|
||||
.UnsafeOr("SQL")
|
||||
.UnsafeOrderBy("SQL")
|
||||
.UnsafeSelect("SQL")
|
||||
.UnsafeWhere("SQL");
|
||||
|
||||
var untyped = expr.GetUntypedSqlExpression();
|
||||
|
||||
untyped
|
||||
.UnsafeAnd("SQL")
|
||||
.UnsafeFrom("SQL")
|
||||
.UnsafeOr("SQL")
|
||||
.UnsafeSelect("SQL")
|
||||
.UnsafeWhere("SQL")
|
||||
.Where("SQL"); // safe
|
||||
|
||||
System.Data.IDbConnection conn = null;
|
||||
|
||||
var row = conn.SingleById<Table>(1); // ok
|
||||
|
||||
var rows = conn.Select<Table>(typeof(Table), "SQL", null);
|
||||
rows = await conn.SelectAsync<Table>(typeof(Table), "SQL", null);
|
||||
|
||||
var count = conn.RowCount("SQL");
|
||||
count = await conn.RowCountAsync("SQL");
|
||||
|
||||
conn.ExecuteSql("SQL", null);
|
||||
await conn.ExecuteSqlAsync("SQL", null);
|
||||
}
|
||||
|
||||
public static async Task Redis()
|
||||
{
|
||||
ServiceStack.Redis.IRedisClient client = null;
|
||||
|
||||
client.SetValue("key", "value"); // ok
|
||||
|
||||
var s = client.LoadLuaScript("script");
|
||||
client.ExecLua("script", new[] { "" }, new[] { "" });
|
||||
client.ExecLuaSha("SHA", new[] { "" }, new[] { "" }); // ok
|
||||
client.Custom("command", "arg"); // false negative, params sinks doesn't work
|
||||
|
||||
ServiceStack.Redis.IRedisClientAsync asyncClient = null;
|
||||
s = await asyncClient.LoadLuaScriptAsync("script");
|
||||
asyncClient.ExecLuaAsync("script", new[] { "" }, new[] { "" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ServiceStack;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace ServiceStackTest
|
||||
{
|
||||
public class XssServices : Service
|
||||
{
|
||||
public object Get(Request1 request)
|
||||
{
|
||||
return "<script>";
|
||||
}
|
||||
|
||||
public object Post(Request1 request) => "<script>";
|
||||
|
||||
private void SomeMethod()
|
||||
{
|
||||
var s = new HttpResult("", ""); // not a sink
|
||||
}
|
||||
|
||||
public object Delete(Request1 req) => req; // not a sink
|
||||
|
||||
public object Put(Request1 req) => new HttpResult("", "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ServiceStack;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace ServiceStackTest
|
||||
{
|
||||
public class MyServices1 : Service
|
||||
{
|
||||
public object Get(string request) => throw null; // this might not be a remote source
|
||||
public object Get(Request1 request) => throw null;
|
||||
public object Get(Request2 request) => throw null;
|
||||
public object Get(Request3 request) => throw null; // might be a remote source if routes are looked up with Routes.AddFromAssembly
|
||||
public object Get(Request4 request)
|
||||
{
|
||||
Console.WriteLine(request.Nested.Prop1);
|
||||
Console.WriteLine(request.Nested.Prop2[0].Prop1);
|
||||
throw null;
|
||||
}
|
||||
|
||||
public object Post(Request1 request) => throw null;
|
||||
public Task<object> PostAsync(Request1 request) => throw null;
|
||||
public object Method1(Request1 request) // Not a request method
|
||||
{
|
||||
Console.WriteLine(request.Field1);
|
||||
throw null;
|
||||
}
|
||||
|
||||
public object GetJson(Request1 request) => throw null;
|
||||
}
|
||||
|
||||
public class MyServices2 : IService
|
||||
{
|
||||
public object Get(Request1 request) => throw null;
|
||||
}
|
||||
|
||||
public class Request1 : IReturn<Response1>
|
||||
{
|
||||
public string Field1;
|
||||
}
|
||||
|
||||
public class Response1
|
||||
{
|
||||
public string Result { get; set; }
|
||||
}
|
||||
|
||||
[Route("/req2/{Prop1}")]
|
||||
public class Request2
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
}
|
||||
|
||||
public class Request3
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
}
|
||||
|
||||
[Route("/req4")]
|
||||
public class Request4 : IReturnVoid
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
public Nested Nested { get; set; }
|
||||
}
|
||||
|
||||
public class Nested
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
public List<Element> Prop2 { get; set; }
|
||||
}
|
||||
|
||||
public class Element
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
| SinksInjection.cs:64:42:64:49 | "script" | SinksInjection.cs:64:42:64:49 | "script" |
|
||||
| SinksInjection.cs:65:28:65:35 | "script" | SinksInjection.cs:65:28:65:35 | "script" |
|
||||
| SinksInjection.cs:70:54:70:61 | "script" | SinksInjection.cs:70:54:70:61 | "script" |
|
||||
| SinksInjection.cs:71:38:71:45 | "script" | SinksInjection.cs:71:38:71:45 | "script" |
|
||||
@@ -0,0 +1,7 @@
|
||||
import semmle.code.csharp.security.dataflow.CodeInjectionQuery
|
||||
|
||||
from Sink sink
|
||||
where
|
||||
sink.getLocation().getFile().fromSource() and
|
||||
not sink.getLocation().getFile().getAbsolutePath().matches("%/resources/stubs/%")
|
||||
select sink, sink.getExpr()
|
||||
@@ -0,0 +1,26 @@
|
||||
| SinksExternal.cs:24:24:24:36 | object creation of type ReqDto1 | SinksExternal.cs:24:24:24:36 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:25:24:25:36 | object creation of type ReqDto2 | SinksExternal.cs:25:24:25:36 | object creation of type ReqDto2 |
|
||||
| SinksExternal.cs:27:37:27:48 | object creation of type Object | SinksExternal.cs:27:37:27:48 | object creation of type Object |
|
||||
| SinksExternal.cs:29:24:29:35 | object creation of type Object | SinksExternal.cs:29:24:29:35 | object creation of type Object |
|
||||
| SinksExternal.cs:32:48:32:59 | object creation of type Object | SinksExternal.cs:32:48:32:59 | object creation of type Object |
|
||||
| SinksExternal.cs:33:35:33:47 | object creation of type ReqDto1 | SinksExternal.cs:33:35:33:47 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:34:35:34:47 | object creation of type ReqDto2 | SinksExternal.cs:34:35:34:47 | object creation of type ReqDto2 |
|
||||
| SinksExternal.cs:37:40:37:52 | object creation of type ReqDto2 | SinksExternal.cs:37:40:37:52 | object creation of type ReqDto2 |
|
||||
| SinksExternal.cs:38:78:38:90 | object creation of type ReqDto1 | SinksExternal.cs:38:78:38:90 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:39:53:39:65 | object creation of type ReqDto1 | SinksExternal.cs:39:53:39:65 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:40:53:40:64 | object creation of type Object | SinksExternal.cs:40:53:40:64 | object creation of type Object |
|
||||
| SinksExternal.cs:41:65:41:76 | object creation of type Object | SinksExternal.cs:41:65:41:76 | object creation of type Object |
|
||||
| SinksExternal.cs:42:40:42:56 | (...) ... | SinksExternal.cs:42:40:42:56 | (...) ... |
|
||||
| SinksExternal.cs:43:51:43:63 | object creation of type ReqDto2 | SinksExternal.cs:43:51:43:63 | object creation of type ReqDto2 |
|
||||
| SinksExternal.cs:44:89:44:101 | object creation of type ReqDto1 | SinksExternal.cs:44:89:44:101 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:45:64:45:76 | object creation of type ReqDto1 | SinksExternal.cs:45:64:45:76 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:46:64:46:75 | object creation of type Object | SinksExternal.cs:46:64:46:75 | object creation of type Object |
|
||||
| SinksExternal.cs:48:55:48:66 | object creation of type Object | SinksExternal.cs:48:55:48:66 | object creation of type Object |
|
||||
| SinksExternal.cs:49:77:49:88 | object creation of type Object | SinksExternal.cs:49:77:49:88 | object creation of type Object |
|
||||
| SinksExternal.cs:51:25:51:36 | object creation of type Object | SinksExternal.cs:51:25:51:36 | object creation of type Object |
|
||||
| SinksExternal.cs:52:26:52:37 | object creation of type Object | SinksExternal.cs:52:26:52:37 | object creation of type Object |
|
||||
| SinksExternal.cs:53:25:53:36 | object creation of type Object | SinksExternal.cs:53:25:53:36 | object creation of type Object |
|
||||
| SinksExternal.cs:54:24:54:35 | object creation of type Object | SinksExternal.cs:54:24:54:35 | object creation of type Object |
|
||||
| SinksExternal.cs:56:38:56:49 | object creation of type Object | SinksExternal.cs:56:38:56:49 | object creation of type Object |
|
||||
| SinksExternal.cs:57:28:57:40 | object creation of type ReqDto1 | SinksExternal.cs:57:28:57:40 | object creation of type ReqDto1 |
|
||||
| SinksExternal.cs:58:31:58:42 | object creation of type Object | SinksExternal.cs:58:31:58:42 | object creation of type Object |
|
||||
@@ -0,0 +1,7 @@
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
|
||||
|
||||
from ExternalLocationSink sink
|
||||
where
|
||||
sink.getLocation().getFile().fromSource() and
|
||||
not sink.getLocation().getFile().getAbsolutePath().matches("%/resources/stubs/%")
|
||||
select sink, sink.getExpr()
|
||||
@@ -0,0 +1,3 @@
|
||||
semmle-extractor-options: /nostdlib /noconfig
|
||||
semmle-extractor-options: --load-sources-from-project:../../../resources/stubs/ServiceStack/5.11.0/ServiceStack.csproj
|
||||
semmle-extractor-options: --load-sources-from-project:../../../resources/stubs/ServiceStack.OrmLite.SqlServer/5.11.0/ServiceStack.OrmLite.SqlServer.csproj
|
||||
@@ -0,0 +1,13 @@
|
||||
| SinksXss.cs:11:36:11:42 | request | ServiceStack request parameter |
|
||||
| SinksXss.cs:16:37:16:43 | request | ServiceStack request parameter |
|
||||
| SinksXss.cs:23:39:23:41 | req | ServiceStack request parameter |
|
||||
| SinksXss.cs:25:36:25:38 | req | ServiceStack request parameter |
|
||||
| Sources.cs:11:34:11:40 | request | ServiceStack request parameter |
|
||||
| Sources.cs:12:36:12:42 | request | ServiceStack request parameter |
|
||||
| Sources.cs:13:36:13:42 | request | ServiceStack request parameter |
|
||||
| Sources.cs:14:36:14:42 | request | ServiceStack request parameter |
|
||||
| Sources.cs:15:36:15:42 | request | ServiceStack request parameter |
|
||||
| Sources.cs:22:37:22:43 | request | ServiceStack request parameter |
|
||||
| Sources.cs:23:48:23:54 | request | ServiceStack request parameter |
|
||||
| Sources.cs:30:40:30:46 | request | ServiceStack request parameter |
|
||||
| Sources.cs:35:36:35:42 | request | ServiceStack request parameter |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user