Merge branch 'main' into reuse-even-more-nodes

This commit is contained in:
Mathias Vorreiter Pedersen
2023-08-26 18:08:58 +01:00
745 changed files with 49796 additions and 33571 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Only the 2 level indirection of `argv` (corresponding to `**argv`) is consided for `FlowSource`.

View File

@@ -53,7 +53,7 @@ private class ArgvSource extends LocalFlowSource {
exists(Function main, Parameter argv |
main.hasGlobalName("main") and
main.getParameter(1) = argv and
this.asParameter(_) = argv
this.asParameter(2) = argv
)
}

View File

@@ -105,8 +105,6 @@ predicate isNonConst(DataFlow::Node node, boolean isIndirect) {
or
e instanceof NewArrayExpr
or
e instanceof AssignExpr
or
exists(Variable v | v = e.(VariableAccess).getTarget() |
v.getType().(ArrayType).getBaseType() instanceof CharType and
exists(AssignExpr ae |

View File

@@ -14,9 +14,11 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
import TaintedWithPath
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.TaintTracking
import SqlTainted::PathGraph
class SqlLikeFunction extends FunctionWithWrappers {
SqlLikeFunction() { sqlArgument(this.getName(), _) }
@@ -24,31 +26,43 @@ class SqlLikeFunction extends FunctionWithWrappers {
override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) }
}
class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) {
exists(SqlLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _))
Expr asSinkExpr(DataFlow::Node node) {
result = node.asIndirectArgument()
or
// We want the conversion so we only get one node for the expression
result = node.asConvertedExpr()
}
module SqlTaintedConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
predicate isSink(DataFlow::Node node) {
exists(SqlLikeFunction runSql | runSql.outermostWrapperFunctionCall(asSinkExpr(node), _))
}
override predicate isBarrier(Expr e) {
super.isBarrier(e)
or
e.getUnspecifiedType() instanceof IntegralType
or
predicate isBarrier(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
predicate isBarrierIn(DataFlow::Node node) {
exists(SqlBarrierFunction sql, int arg, FunctionInput input |
e = sql.getACallToThisFunction().getArgument(arg) and
node.asIndirectArgument() = sql.getACallToThisFunction().getArgument(arg) and
input.isParameterDeref(arg) and
sql.barrierSqlArgument(input, _)
)
}
}
module SqlTainted = TaintTracking::Global<SqlTaintedConfig>;
from
SqlLikeFunction runSql, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode,
string taintCause, string callChain
SqlLikeFunction runSql, Expr taintedArg, FlowSource taintSource, SqlTainted::PathNode sourceNode,
SqlTainted::PathNode sinkNode, string callChain
where
runSql.outermostWrapperFunctionCall(taintedArg, callChain) and
taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and
isUserInput(taintSource, taintCause)
SqlTainted::flowPath(sourceNode, sinkNode) and
taintedArg = asSinkExpr(sinkNode.getNode()) and
taintSource = sourceNode.getNode()
select taintedArg, sourceNode, sinkNode,
"This argument to a SQL query function is derived from $@ and then passed to " + callChain + ".",
taintSource, "user input (" + taintCause + ")"
taintSource, "user input (" + taintSource.getSourceType() + ")"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Some queries that had repeated results corresponding to different levels of indirection for `argv` now only have a single result.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/non-constant-format` query no longer considers an assignment on the right-hand side of another assignment to be a source of non-constant format strings. As a result, the query may now produce fewer results.

View File

@@ -40,7 +40,7 @@ module WordexpTaintConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
fc.getArgument(0) = sink.asExpr() and
fc.getArgument(0) = sink.asIndirectArgument(1) and
not isCommandSubstitutionDisabled(fc)
)
}

View File

@@ -1,16 +1,8 @@
edges
| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath indirection |
nodes
| test.cpp:22:27:22:30 | argv | semmle.label | argv |
| test.cpp:22:27:22:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:29:13:29:20 | filePath | semmle.label | filePath |
| test.cpp:29:13:29:20 | filePath | semmle.label | filePath |
| test.cpp:29:13:29:20 | filePath indirection | semmle.label | filePath indirection |
subpaths
#select
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath indirection | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath indirection | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |

View File

@@ -1798,6 +1798,23 @@ ir.c:
# 10| Type = [CTypedefType] MyCoords
# 10| ValueCategory = lvalue
# 11| getStmt(3): [ReturnStmt] return ...
# 13| [TopLevelFunction] void CStyleCast(void*)
# 13| <params>:
# 13| getParameter(0): [Parameter] src
# 13| Type = [VoidPointerType] void *
# 14| getEntryPoint(): [BlockStmt] { ... }
# 15| getStmt(0): [DeclStmt] declaration
# 15| getDeclarationEntry(0): [VariableDeclarationEntry] definition of dst
# 15| Type = [CharPointerType] char *
# 15| getVariable().getInitializer(): [Initializer] initializer for dst
# 15| getExpr(): [VariableAccess] src
# 15| Type = [VoidPointerType] void *
# 15| ValueCategory = prvalue(load)
# 15| getExpr().getFullyConverted(): [CStyleCast] (char *)...
# 15| Conversion = [PointerConversion] pointer conversion
# 15| Type = [CharPointerType] char *
# 15| ValueCategory = prvalue
# 16| getStmt(1): [ReturnStmt] return ...
ir.cpp:
# 1| [TopLevelFunction] void Constants()
# 1| <params>:

View File

@@ -9,3 +9,10 @@ void MyCoordsTest(int pos) {
coords.x = coords.y = pos + 1;
coords.x = getX(&coords);
}
void CStyleCast(void *src)
{
char *dst = (char*)src;
}
// semmle-extractor-options: --microsoft

View File

@@ -978,6 +978,20 @@
| ir.c:10:19:10:25 | ChiTotal | total:m9_13 |
| ir.c:10:19:10:25 | SideEffect | ~m9_13 |
| ir.c:10:20:10:25 | Unary | r10_2 |
| ir.c:13:6:13:15 | ChiPartial | partial:m13_3 |
| ir.c:13:6:13:15 | ChiTotal | total:m13_2 |
| ir.c:13:6:13:15 | SideEffect | m13_3 |
| ir.c:13:23:13:25 | Address | &:r13_5 |
| ir.c:13:23:13:25 | Address | &:r13_5 |
| ir.c:13:23:13:25 | Address | &:r13_7 |
| ir.c:13:23:13:25 | Address | &:r13_7 |
| ir.c:13:23:13:25 | Load | m13_6 |
| ir.c:13:23:13:25 | SideEffect | m13_8 |
| ir.c:15:11:15:13 | Address | &:r15_1 |
| ir.c:15:17:15:26 | StoreValue | r15_4 |
| ir.c:15:24:15:26 | Address | &:r15_2 |
| ir.c:15:24:15:26 | Load | m13_6 |
| ir.c:15:24:15:26 | Unary | r15_3 |
| ir.cpp:1:6:1:14 | ChiPartial | partial:m1_3 |
| ir.cpp:1:6:1:14 | ChiTotal | total:m1_2 |
| ir.cpp:1:6:1:14 | SideEffect | m1_3 |

View File

@@ -766,6 +766,26 @@ ir.c:
# 7| v7_7(void) = AliasedUse : ~m?
# 7| v7_8(void) = ExitFunction :
# 13| void CStyleCast(void*)
# 13| Block 0
# 13| v13_1(void) = EnterFunction :
# 13| mu13_2(unknown) = AliasedDefinition :
# 13| mu13_3(unknown) = InitializeNonLocal :
# 13| r13_4(glval<void *>) = VariableAddress[src] :
# 13| mu13_5(void *) = InitializeParameter[src] : &:r13_4
# 13| r13_6(void *) = Load[src] : &:r13_4, ~m?
# 13| mu13_7(unknown) = InitializeIndirection[src] : &:r13_6
# 15| r15_1(glval<char *>) = VariableAddress[dst] :
# 15| r15_2(glval<void *>) = VariableAddress[src] :
# 15| r15_3(void *) = Load[src] : &:r15_2, ~m?
# 15| r15_4(char *) = Convert : r15_3
# 15| mu15_5(char *) = Store[dst] : &:r15_1, r15_4
# 16| v16_1(void) = NoOp :
# 13| v13_8(void) = ReturnIndirection[src] : &:r13_6, ~m?
# 13| v13_9(void) = ReturnVoid :
# 13| v13_10(void) = AliasedUse : ~m?
# 13| v13_11(void) = ExitFunction :
ir.cpp:
# 1| void Constants()
# 1| Block 0

View File

@@ -156,3 +156,10 @@ void fmt_via_strcpy(char *data) {
strcpy(data, "some string");
printf(data); // BAD
}
void fmt_with_assignment() {
const char *x, *y;
x = y = "a";
printf(y); // GOOD
}

View File

@@ -1,16 +1,10 @@
edges
| test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection |
| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection |
| test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection |
| test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection |
nodes
| test.c:8:27:8:30 | argv | semmle.label | argv |
| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection |
| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection |
| test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection |
| test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection |
@@ -21,12 +15,8 @@ nodes
| test.c:57:10:57:16 | access to array indirection | semmle.label | access to array indirection |
subpaths
#select
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv | user input (a command-line argument) |
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | scanf output argument | user input (value read by scanf) |
| test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | scanf output argument | user input (value read by scanf) |
| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |

View File

@@ -1,6 +1,5 @@
edges
| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection |
| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection |
| test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection |
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:45:22:52 | userName indirection |
@@ -73,7 +72,6 @@ edges
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:19:220:26 | filename indirection |
nodes
| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:22:45:22:52 | userName indirection | semmle.label | userName indirection |
| test.cpp:23:12:23:19 | command1 indirection | semmle.label | command1 indirection |
@@ -156,7 +154,6 @@ subpaths
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument |
#select
| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv indirection | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument |
| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument |
| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument |

View File

@@ -1,25 +1,12 @@
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 |
| 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 |
| 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 |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
subpaths
| test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection |
nodes
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
| 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 | 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.c:14:27:14:30 | argv indirection | semmle.label | argv indirection |
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
subpaths
#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) |
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |

View File

@@ -1,10 +1,6 @@
edges
| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection |
| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:9:53:12 | memcpy output argument |
@@ -21,10 +17,7 @@ edges
| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection |
nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument |
@@ -44,7 +37,6 @@ subpaths
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
#select
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:64:2:64:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:64:16:64:19 | src2 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |

View File

@@ -1,12 +1,6 @@
edges
| test1.c:7:26:7:29 | argv | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv | test1.c:13:9:13:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
| test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i |
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i |
@@ -15,8 +9,6 @@ edges
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i |
| test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j |
nodes
| test1.c:7:26:7:29 | argv | semmle.label | argv |
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
| test1.c:9:9:9:9 | i | semmle.label | i |
| test1.c:11:9:11:9 | i | semmle.label | i |
@@ -29,12 +21,6 @@ nodes
| test1.c:53:15:53:15 | j | semmle.label | j |
subpaths
#select
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |

View File

@@ -1,21 +1,9 @@
edges
| test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
| test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... |
@@ -47,8 +35,6 @@ edges
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size |
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size |
nodes
| test.cpp:39:27:39:30 | argv | semmle.label | argv |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
@@ -92,23 +78,11 @@ nodes
| test.cpp:356:35:356:38 | size | semmle.label | size |
subpaths
#select
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) |
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv indirection | user input (an environment variable) |

View File

@@ -4,7 +4,6 @@ edges
nodes
| test2.cpp:110:3:110:6 | call to gets indirection | semmle.label | call to gets indirection |
| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection |
subpaths
#select

View File

@@ -1,9 +1,11 @@
{
"recommendations": [
"github.vscode-codeql",
"ms-dotnettools.csharp",
"formulahendry.dotnet-test-explorer",
"hbenl.vscode-test-explorer"
"gaoshan0621.csharp-format-usings",
"github.vscode-codeql",
"hbenl.vscode-test-explorer",
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit"
],
"unwantedRecommendations": []
}

View File

@@ -7,5 +7,8 @@
"editor.defaultFormatter": "ms-dotnettools.csharp"
},
"omnisharp.enableEditorConfigSupport": true,
"omnisharp.enableRoslynAnalyzers": true
"omnisharp.enableRoslynAnalyzers": true,
"csharpFormatUsings.splitGroups": false,
"csharpFormatUsings.sortOrder": "Xunit System Microsoft Semmle.Util Semmle",
"dotnet.defaultSolution": "CSharp.sln"
}

View File

@@ -1,53 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "dotnet build",
"command": "dotnet",
"type": "shell",
"args": [
"build",
// Ask dotnet build to generate full paths for file names.
"/property:GenerateFullPaths=true",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
},
{
"label": "dotnet rebuild",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"--no-incremental",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
},
{
"label": "dotnet test",
"command": "dotnet",
"type": "shell",
"args": [
"test",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"group": "test",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -1,4 +1,6 @@
name: "csharp"
aliases:
- "c#"
display_name: "C#"
version: 1.22.1
column_kind: "utf16"

View File

@@ -1,13 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Semmle.Util;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver
{

View File

@@ -1,8 +1,8 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Semmle.Util.Logging;
using System.Diagnostics;
namespace Semmle.Extraction.CIL.Driver
{

View File

@@ -1,6 +1,6 @@
using Semmle.Util.Logging;
using System;
using Semmle.Util;
using Semmle.Util.Logging;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL

View File

@@ -1,8 +1,7 @@
using Semmle.Extraction.CIL.Entities;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{

View File

@@ -1,8 +1,7 @@
using System.Reflection;
using System.Collections.Generic;
using System.Globalization;
using System.Collections.Generic;
using System.Reflection;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,7 +1,7 @@
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,3 @@
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
internal interface ITypeSignature

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,6 +1,6 @@
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,8 +1,7 @@
using System;
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.IO;
using System.Reflection.Metadata;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,4 @@
using System.Linq;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Semmle.Util;

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,6 +1,5 @@
using System.Reflection.Metadata;
using System.Collections.Immutable;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
using Semmle.Extraction.PDB;
namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,8 +1,8 @@
using System.Reflection.Metadata;
using System.Collections.Generic;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,10 +1,10 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,9 +1,9 @@
using System;
using System.Reflection.Metadata;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,8 +1,8 @@
using System;
using System.Reflection.Metadata;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Reflection.Metadata;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,6 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CIL.Entities
{

View File

@@ -1,6 +1,6 @@
using System;
using Microsoft.DiaSymReader;
using System.Reflection;
using Microsoft.DiaSymReader;
#pragma warning disable IDE0060, CA1822

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Microsoft.DiaSymReader;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.Metadata;
using System.IO;
namespace Semmle.Extraction.PDB
{

View File

@@ -59,10 +59,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
// The OrderBy is used to ensure that we by default select the highest version number.
foreach (var info in assemblyInfoByFileName.Values
.OrderBy(info => info.Name)
.ThenBy(info => info.NetCoreVersion ?? emptyVersion)
.ThenBy(info => info.Version ?? emptyVersion))
{
foreach (var index in info.IndexStrings)
{
assemblyInfoById[index] = info;
}
}
}

View File

@@ -5,13 +5,15 @@ using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Reflection.Metadata;
using System.Text.RegularExpressions;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
/// <summary>
/// Stores information about an assembly file (DLL).
/// </summary>
internal sealed class AssemblyInfo
internal sealed partial class AssemblyInfo
{
/// <summary>
/// The file containing the assembly.
@@ -28,6 +30,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// </summary>
public System.Version? Version { get; }
/// <summary>
/// The version number of the .NET Core framework that this assembly targets.
///
/// This is extracted from the `TargetFrameworkAttribute` of the assembly, e.g.
/// ```
/// [assembly:TargetFramework(".NETCoreApp,Version=v7.0")]
/// ```
/// yields version 7.0.
/// </summary>
public Version? NetCoreVersion { get; }
/// <summary>
/// The public key token of the assembly.
/// </summary>
@@ -97,13 +110,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
Filename = filename;
}
private AssemblyInfo(string filename, string name, Version version, string culture, string publicKeyToken)
private AssemblyInfo(string filename, string name, Version version, string culture, string publicKeyToken, Version? netCoreVersion)
{
Filename = filename;
Name = name;
Version = version;
Culture = culture;
PublicKeyToken = publicKeyToken;
NetCoreVersion = netCoreVersion;
}
/// <summary>
@@ -150,7 +164,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var metadata = pereader.GetMetadata();
unsafe
{
var reader = new System.Reflection.Metadata.MetadataReader(metadata.Pointer, metadata.Length);
var reader = new MetadataReader(metadata.Pointer, metadata.Length);
var def = reader.GetAssemblyDefinition();
// This is how you compute the public key token from the full public key.
@@ -162,7 +176,39 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
publicKeyString.AppendFormat("{0:x2}", b);
var culture = def.Culture.IsNil ? "neutral" : reader.GetString(def.Culture);
return new AssemblyInfo(filename, reader.GetString(def.Name), def.Version, culture, publicKeyString.ToString());
Version? netCoreVersion = null;
foreach (var attrHandle in def.GetCustomAttributes().Select(reader.GetCustomAttribute))
{
var ctorHandle = attrHandle.Constructor;
if (ctorHandle.Kind != HandleKind.MemberReference)
{
continue;
}
var mHandle = reader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent;
if (mHandle.Kind != HandleKind.TypeReference)
{
continue;
}
var name = reader.GetString(reader.GetTypeReference((TypeReferenceHandle)mHandle).Name);
if (name is "TargetFrameworkAttribute")
{
var decoded = attrHandle.DecodeValue(new DummyAttributeDecoder());
if (
decoded.FixedArguments.Length > 0 &&
decoded.FixedArguments[0].Value is string value &&
NetCoreAppRegex().Match(value).Groups.TryGetValue("version", out var match))
{
netCoreVersion = new Version(match.Value);
}
break;
}
}
return new AssemblyInfo(filename, reader.GetString(def.Name), def.Version, culture, publicKeyString.ToString(), netCoreVersion);
}
}
catch (BadImageFormatException)
@@ -176,5 +222,33 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
throw new AssemblyLoadException();
}
[GeneratedRegex(@"^\.NETCoreApp,Version=v(?<version>\d+\.\d+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
private static partial Regex NetCoreAppRegex();
private class DummyAttributeDecoder : ICustomAttributeTypeProvider<int>
{
public int GetPrimitiveType(PrimitiveTypeCode typeCode) => 0;
public int GetSystemType() => throw new NotImplementedException();
public int GetSZArrayType(int elementType) =>
throw new NotImplementedException();
public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) =>
throw new NotImplementedException();
public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) =>
throw new NotImplementedException();
public int GetTypeFromSerializedName(string name) =>
throw new NotImplementedException();
public PrimitiveTypeCode GetUnderlyingEnumType(int type) =>
throw new NotImplementedException();
public bool IsSystemType(int type) => throw new NotImplementedException();
}
}
}

View File

@@ -23,13 +23,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private readonly IDictionary<string, string> unresolvedReferences = new ConcurrentDictionary<string, string>();
private int failedProjects;
private int succeededProjects;
private readonly string[] allSources;
private readonly List<string> allSources;
private int conflictedReferences = 0;
private readonly IDependencyOptions options;
private readonly DirectoryInfo sourceDir;
private readonly DotNet dotnet;
private readonly FileContent fileContent;
private readonly TemporaryDirectory packageDirectory;
private TemporaryDirectory? razorWorkingDirectory;
/// <summary>
@@ -59,8 +60,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName));
this.fileContent = new FileContent(packageDirectory, progressMonitor, () => GetFiles("*.*"));
this.allSources = GetFiles("*.cs").ToArray();
this.fileContent = new FileContent(progressMonitor, () => GetFiles("*.*"));
this.allSources = GetFiles("*.cs").ToList();
var allProjects = GetFiles("*.csproj");
var solutions = options.SolutionFile is not null
? new[] { options.SolutionFile }
@@ -121,16 +122,23 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
ResolveConflicts();
// Output the findings
foreach (var r in usedReferences.Keys)
foreach (var r in usedReferences.Keys.OrderBy(r => r))
{
progressMonitor.ResolvedReference(r);
}
foreach (var r in unresolvedReferences)
foreach (var r in unresolvedReferences.OrderBy(r => r.Key))
{
progressMonitor.UnresolvedReference(r.Key, r.Value);
}
var webViewExtractionOption = Environment.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_STANDALONE_EXTRACT_WEB_VIEWS");
if (bool.TryParse(webViewExtractionOption, out var shouldExtractWebViews) &&
shouldExtractWebViews)
{
GenerateSourceFilesFromWebViews();
}
progressMonitor.Summary(
AllSourceFiles.Count(),
ProjectSourceFiles.Count(),
@@ -143,22 +151,56 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
DateTime.Now - startTime);
}
private void GenerateSourceFilesFromWebViews()
{
progressMonitor.LogInfo($"Generating source files from cshtml and razor files.");
var views = GetFiles("*.cshtml")
.Concat(GetFiles("*.razor"))
.ToArray();
if (views.Length > 0)
{
progressMonitor.LogInfo($"Found {views.Length} cshtml and razor files.");
// TODO: use SDK specified in global.json
var sdk = new Sdk(dotnet).GetNewestSdk();
if (sdk != null)
{
try
{
var razor = new Razor(sdk, dotnet, progressMonitor);
razorWorkingDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName, "razor"));
var generatedFiles = razor.GenerateFiles(views, usedReferences.Keys, razorWorkingDirectory.ToString());
this.allSources.AddRange(generatedFiles);
}
catch (Exception ex)
{
// It's okay, we tried our best to generate source files from cshtml files.
progressMonitor.LogInfo($"Failed to generate source files from cshtml files: {ex.Message}");
}
}
}
}
public DependencyManager(string srcDir) : this(srcDir, DependencyOptions.Default, new ConsoleLogger(Verbosity.Info)) { }
private IEnumerable<string> GetFiles(string pattern, bool recurseSubdirectories = true)
{
return sourceDir.GetFiles(pattern, new EnumerationOptions { RecurseSubdirectories = recurseSubdirectories, MatchCasing = MatchCasing.CaseInsensitive })
private IEnumerable<string> GetFiles(string pattern, bool recurseSubdirectories = true) =>
sourceDir.GetFiles(pattern, new EnumerationOptions
{
RecurseSubdirectories = recurseSubdirectories,
MatchCasing = MatchCasing.CaseInsensitive
})
.Where(d => d.Extension != ".dll")
.Select(d => d.FullName)
.Where(d => !options.ExcludesFile(d));
}
/// <summary>
/// Computes a unique temp directory for the packages associated
/// with this source tree. Use a SHA1 of the directory name.
/// </summary>
/// <param name="srcDir"></param>
/// <returns>The full path of the temp directory.</returns>
private static string ComputeTempDirectory(string srcDir)
private static string ComputeTempDirectory(string srcDir, string subfolderName = "packages")
{
var bytes = Encoding.Unicode.GetBytes(srcDir);
var sha = SHA1.HashData(bytes);
@@ -166,7 +208,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
foreach (var b in sha.Take(8))
sb.AppendFormat("{0:x2}", b);
return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString());
return Path.Combine(Path.GetTempPath(), "GitHub", subfolderName, sb.ToString());
}
/// <summary>
@@ -190,7 +232,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
sortedReferences = sortedReferences.OrderBy(r => r.Version).ToList();
var emptyVersion = new Version(0, 0);
sortedReferences = sortedReferences.OrderBy(r => r.NetCoreVersion ?? emptyVersion).ThenBy(r => r.Version ?? emptyVersion).ToList();
var finalAssemblyList = new Dictionary<string, AssemblyInfo>();
@@ -211,9 +254,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
foreach (var r in sortedReferences)
{
var resolvedInfo = finalAssemblyList[r.Name];
if (resolvedInfo.Version != r.Version)
if (resolvedInfo.Version != r.Version || resolvedInfo.NetCoreVersion != r.NetCoreVersion)
{
progressMonitor.ResolvedConflict(r.Id, resolvedInfo.Id);
progressMonitor.ResolvedConflict(r.Id, resolvedInfo.Id + resolvedInfo.NetCoreVersion is null ? "" : $" (.NET Core {resolvedInfo.NetCoreVersion})");
++conflictedReferences;
}
}
@@ -349,7 +392,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
nugetConfig = nugetConfigs.FirstOrDefault();
}
foreach (var package in fileContent.NotYetDownloadedPackages)
var alreadyDownloadedPackages = Directory.GetDirectories(packageDirectory.DirInfo.FullName)
.Select(d => Path.GetFileName(d)
.ToLowerInvariant());
var notYetDownloadedPackages = fileContent.AllPackages.Except(alreadyDownloadedPackages);
foreach (var package in notYetDownloadedPackages)
{
progressMonitor.NugetInstall(package);
using var tempDir = new TemporaryDirectory(ComputeTempDirectory(package));
@@ -377,7 +424,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void AnalyseSolutions(IEnumerable<string> solutions)
{
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, solutionFile =>
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, solutionFile =>
{
try
{
@@ -392,6 +439,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
});
}
public void Dispose() => packageDirectory?.Dispose();
public void Dispose()
{
packageDirectory?.Dispose();
razorWorkingDirectory?.Dispose();
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
@@ -49,6 +51,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// <param name="path">The path to query.</param>
/// <returns>True iff the path matches an exclusion.</returns>
bool ExcludesFile(string path);
/// <summary>
/// The number of threads to use.
/// </summary>
int Threads { get; }
}
public class DependencyOptions : IDependencyOptions
@@ -71,5 +78,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
public bool ExcludesFile(string path) =>
Excludes.Any(path.Contains);
public int Threads { get; set; } = EnvironmentVariables.GetDefaultNumberOfThreads();
}
}

View File

@@ -5,14 +5,6 @@ using Semmle.Util;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal interface IDotNet
{
bool RestoreToDirectory(string project, string directory, string? pathToNugetConfig = null);
bool New(string folder);
bool AddPackage(string folder, string package);
IList<string> GetListedRuntimes();
}
/// <summary>
/// Utilities to run the "dotnet" command.
/// </summary>
@@ -30,29 +22,31 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void Info()
{
// TODO: make sure the below `dotnet` version is matching the one specified in global.json
progressMonitor.RunningProcess($"{dotnet} --info");
using var proc = Process.Start(dotnet, "--info");
proc.WaitForExit();
var ret = proc.ExitCode;
if (ret != 0)
var res = RunCommand("--info");
if (!res)
{
progressMonitor.CommandFailed(dotnet, "--info", ret);
throw new Exception($"{dotnet} --info failed with exit code {ret}.");
throw new Exception($"{dotnet} --info failed.");
}
}
private static ProcessStartInfo MakeDotnetStartInfo(string args, bool redirectStandardOutput) =>
new ProcessStartInfo(dotnet, args)
{
UseShellExecute = false,
RedirectStandardOutput = redirectStandardOutput
};
private bool RunCommand(string args)
{
progressMonitor.RunningProcess($"{dotnet} {args}");
using var proc = Process.Start(dotnet, args);
proc.WaitForExit();
if (proc.ExitCode != 0)
using var proc = Process.Start(MakeDotnetStartInfo(args, redirectStandardOutput: false));
proc?.WaitForExit();
var exitCode = proc?.ExitCode ?? -1;
if (exitCode != 0)
{
progressMonitor.CommandFailed(dotnet, args, proc.ExitCode);
progressMonitor.CommandFailed(dotnet, args, exitCode);
return false;
}
return true;
}
@@ -76,23 +70,28 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return RunCommand(args);
}
public IList<string> GetListedRuntimes()
public IList<string> GetListedRuntimes() => GetListed("--list-runtimes", "runtime");
public IList<string> GetListedSdks() => GetListed("--list-sdks", "SDK");
private IList<string> GetListed(string args, string artifact)
{
const string args = "--list-runtimes";
progressMonitor.RunningProcess($"{dotnet} {args}");
var pi = new ProcessStartInfo(dotnet, args)
{
RedirectStandardOutput = true,
UseShellExecute = false
};
var exitCode = pi.ReadOutput(out var runtimes);
var pi = MakeDotnetStartInfo(args, redirectStandardOutput: true);
var exitCode = pi.ReadOutput(out var artifacts);
if (exitCode != 0)
{
progressMonitor.CommandFailed(dotnet, args, exitCode);
return new List<string>();
}
progressMonitor.LogInfo($"Found runtimes: {string.Join("\n", runtimes)}");
return runtimes;
progressMonitor.LogInfo($"Found {artifact}s: {string.Join("\n", artifacts)}");
return artifacts;
}
public bool Exec(string execArgs)
{
var args = $"exec {execArgs}";
return RunCommand(args);
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.IO;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal record DotnetVersion : IComparable<DotnetVersion>
{
private readonly string dir;
private readonly Version version;
private readonly Version? preReleaseVersion;
private readonly string? preReleaseVersionType;
private bool IsPreRelease => preReleaseVersionType is not null && preReleaseVersion is not null;
public string FullPath
{
get
{
var preRelease = IsPreRelease ? $"-{preReleaseVersionType}.{preReleaseVersion}" : "";
var version = this.version + preRelease;
return Path.Combine(dir, version);
}
}
public DotnetVersion(string dir, string version, string preReleaseVersionType, string preReleaseVersion)
{
this.dir = dir;
this.version = Version.Parse(version);
if (!string.IsNullOrEmpty(preReleaseVersion) && !string.IsNullOrEmpty(preReleaseVersionType))
{
this.preReleaseVersionType = preReleaseVersionType;
this.preReleaseVersion = Version.Parse(preReleaseVersion);
}
}
public int CompareTo(DotnetVersion? other)
{
var c = version.CompareTo(other?.version);
if (c == 0 && IsPreRelease)
{
if (!other!.IsPreRelease)
{
return -1;
}
// Both are pre-release like runtime versions.
// The pre-release version types are sorted alphabetically (e.g. alpha, beta, preview, rc)
// and the pre-release version types are more important that the pre-release version numbers.
return preReleaseVersionType != other!.preReleaseVersionType
? preReleaseVersionType!.CompareTo(other!.preReleaseVersionType)
: preReleaseVersion!.CompareTo(other!.preReleaseVersion);
}
return c;
}
public override string ToString() => FullPath;
}
}

View File

@@ -12,23 +12,22 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
// This class is used to read a set of files and decide different properties about the
// content (by reading the content of the files only once).
// The implementation is lazy, so the properties are only calculated when
// the first property is accessed.
// the first property is accessed.
// </summary>
internal partial class FileContent
{
private readonly ProgressMonitor progressMonitor;
private readonly IUnsafeFileReader unsafeFileReader;
private readonly Func<IEnumerable<string>> getFiles;
private readonly Func<HashSet<string>> getAlreadyDownloadedPackages;
private readonly HashSet<string> notYetDownloadedPackages = new HashSet<string>();
private readonly HashSet<string> allPackages = new HashSet<string>();
private readonly Initializer initialize;
public HashSet<string> NotYetDownloadedPackages
public HashSet<string> AllPackages
{
get
{
initialize.Run();
return notYetDownloadedPackages;
return allPackages;
}
}
@@ -50,12 +49,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
internal FileContent(Func<HashSet<string>> getAlreadyDownloadedPackages,
ProgressMonitor progressMonitor,
internal FileContent(ProgressMonitor progressMonitor,
Func<IEnumerable<string>> getFiles,
IUnsafeFileReader unsafeFileReader)
{
this.getAlreadyDownloadedPackages = getAlreadyDownloadedPackages;
this.progressMonitor = progressMonitor;
this.getFiles = getFiles;
this.unsafeFileReader = unsafeFileReader;
@@ -63,10 +60,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
public FileContent(TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor, Func<IEnumerable<string>> getFiles) : this(() => Directory.GetDirectories(packageDirectory.DirInfo.FullName)
.Select(d => Path.GetFileName(d)
.ToLowerInvariant())
.ToHashSet(), progressMonitor, getFiles, new UnsafeFileReader())
public FileContent(ProgressMonitor progressMonitor, Func<IEnumerable<string>> getFiles) : this(progressMonitor, getFiles, new UnsafeFileReader())
{ }
private static string GetGroup(ReadOnlySpan<char> input, ValueMatch valueMatch, string groupPrefix)
@@ -101,7 +95,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void DoInitialize()
{
var alreadyDownloadedPackages = getAlreadyDownloadedPackages();
foreach (var file in getFiles())
{
try
@@ -109,14 +102,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
foreach (ReadOnlySpan<char> line in unsafeFileReader.ReadLines(file))
{
// Find the not yet downloaded packages.
// Find all the packages.
foreach (var valueMatch in PackageReference().EnumerateMatches(line))
{
// We can't get the group from the ValueMatch, so doing it manually:
var packageName = GetGroup(line, valueMatch, "Include");
if (!string.IsNullOrEmpty(packageName) && !alreadyDownloadedPackages.Contains(packageName))
if (!string.IsNullOrEmpty(packageName))
{
notYetDownloadedPackages.Add(packageName);
allPackages.Add(packageName);
}
}

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal interface IDotNet
{
bool RestoreToDirectory(string project, string directory, string? pathToNugetConfig = null);
bool New(string folder);
bool AddPackage(string folder, string package);
IList<string> GetListedRuntimes();
IList<string> GetListedSdks();
bool Exec(string execArgs);
}
}

View File

@@ -108,5 +108,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
internal void NoTopLevelNugetConfig() =>
LogInfo("Could not find a top-level nuget.config file.");
internal void RazorSourceGeneratorMissing(string fullPath) =>
LogInfo($"Razor source generator folder {fullPath} does not exist.");
internal void CscMissing(string cscPath) =>
LogInfo($"Csc.exe not found at {cscPath}.");
internal void RazorCscArgs(string args) =>
LogInfo($"Running CSC to generate Razor source files. Args: {args}.");
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal class Razor
{
private readonly DotnetVersion sdk;
private readonly ProgressMonitor progressMonitor;
private readonly DotNet dotNet;
private readonly string sourceGeneratorFolder;
private readonly string cscPath;
public Razor(DotnetVersion sdk, DotNet dotNet, ProgressMonitor progressMonitor)
{
this.sdk = sdk;
this.progressMonitor = progressMonitor;
this.dotNet = dotNet;
sourceGeneratorFolder = Path.Combine(this.sdk.FullPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
if (!Directory.Exists(sourceGeneratorFolder))
{
this.progressMonitor.RazorSourceGeneratorMissing(sourceGeneratorFolder);
throw new Exception($"Razor source generator folder {sourceGeneratorFolder} does not exist.");
}
cscPath = Path.Combine(this.sdk.FullPath, "Roslyn", "bincore", "csc.dll");
if (!File.Exists(cscPath))
{
this.progressMonitor.CscMissing(cscPath);
throw new Exception($"csc.dll {cscPath} does not exist.");
}
}
private static void GenerateAnalyzerConfig(IEnumerable<string> cshtmls, string analyzerConfigPath)
{
using var sw = new StreamWriter(analyzerConfigPath);
sw.WriteLine("is_global = true");
foreach (var f in cshtmls.Select(f => f.Replace('\\', '/')))
{
sw.WriteLine($"\n[{f}]");
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(f)); // TODO: this should be the relative path of the file.
sw.WriteLine($"build_metadata.AdditionalFiles.TargetPath = {base64}");
}
}
public IEnumerable<string> GenerateFiles(IEnumerable<string> cshtmls, IEnumerable<string> references, string workingDirectory)
{
var name = Guid.NewGuid().ToString("N").ToUpper();
var tempPath = Path.GetTempPath();
var analyzerConfig = Path.Combine(tempPath, $"{name}.txt");
var dllPath = Path.Combine(tempPath, $"{name}.dll");
var cscArgsPath = Path.Combine(tempPath, $"{name}.rsp");
var outputFolder = Path.Combine(workingDirectory, name);
Directory.CreateDirectory(outputFolder);
try
{
GenerateAnalyzerConfig(cshtmls, analyzerConfig);
progressMonitor.LogInfo($"Analyzer config content: {File.ReadAllText(analyzerConfig)}");
var args = new StringBuilder();
args.Append($"/target:exe /generatedfilesout:\"{outputFolder}\" /out:\"{dllPath}\" /analyzerconfig:\"{analyzerConfig}\" ");
foreach (var f in Directory.GetFiles(sourceGeneratorFolder, "*.dll"))
{
args.Append($"/analyzer:\"{f}\" ");
}
foreach (var f in cshtmls)
{
args.Append($"/additionalfile:\"{f}\" ");
}
foreach (var f in references)
{
args.Append($"/reference:\"{f}\" ");
}
var argsString = args.ToString();
progressMonitor.RazorCscArgs(argsString);
using (var sw = new StreamWriter(cscArgsPath))
{
sw.Write(argsString);
}
dotNet.Exec($"\"{cscPath}\" /noconfig @\"{cscArgsPath}\"");
return Directory.GetFiles(outputFolder, "*.*", new EnumerationOptions { RecurseSubdirectories = true });
}
finally
{
DeleteFile(analyzerConfig);
DeleteFile(dllPath);
DeleteFile(cscArgsPath);
}
}
private static void DeleteFile(string path)
{
try
{
File.Delete(path);
}
catch
{
// Ignore
}
}
}
}

View File

@@ -17,8 +17,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private const string aspNetCoreApp = "Microsoft.AspNetCore.App";
private readonly IDotNet dotNet;
private readonly Lazy<Dictionary<string, RuntimeVersion>> newestRuntimes;
private Dictionary<string, RuntimeVersion> NewestRuntimes => newestRuntimes.Value;
private readonly Lazy<Dictionary<string, DotnetVersion>> newestRuntimes;
private Dictionary<string, DotnetVersion> NewestRuntimes => newestRuntimes.Value;
private static string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
public Runtime(IDotNet dotNet)
@@ -27,58 +27,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
this.newestRuntimes = new(GetNewestRuntimes);
}
internal record RuntimeVersion : IComparable<RuntimeVersion>
{
private readonly string dir;
private readonly Version version;
private readonly Version? preReleaseVersion;
private readonly string? preReleaseVersionType;
private bool IsPreRelease => preReleaseVersionType is not null && preReleaseVersion is not null;
public string FullPath
{
get
{
var preRelease = IsPreRelease ? $"-{preReleaseVersionType}.{preReleaseVersion}" : "";
var version = this.version + preRelease;
return Path.Combine(dir, version);
}
}
public RuntimeVersion(string dir, string version, string preReleaseVersionType, string preReleaseVersion)
{
this.dir = dir;
this.version = Version.Parse(version);
if (!string.IsNullOrEmpty(preReleaseVersion) && !string.IsNullOrEmpty(preReleaseVersionType))
{
this.preReleaseVersionType = preReleaseVersionType;
this.preReleaseVersion = Version.Parse(preReleaseVersion);
}
}
public int CompareTo(RuntimeVersion? other)
{
var c = version.CompareTo(other?.version);
if (c == 0 && IsPreRelease)
{
if (!other!.IsPreRelease)
{
return -1;
}
// Both are pre-release like runtime versions.
// The pre-release version types are sorted alphabetically (e.g. alpha, beta, preview, rc)
// and the pre-release version types are more important that the pre-release version numbers.
return preReleaseVersionType != other!.preReleaseVersionType
? preReleaseVersionType!.CompareTo(other!.preReleaseVersionType)
: preReleaseVersion!.CompareTo(other!.preReleaseVersion);
}
return c;
}
public override string ToString() => FullPath;
}
[GeneratedRegex(@"^(\S+)\s(\d+\.\d+\.\d+)(-([a-z]+)\.(\d+\.\d+\.\d+))?\s\[(.+)\]$")]
private static partial Regex RuntimeRegex();
@@ -88,16 +36,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// It is assume that the format of a listed runtime is something like:
/// Microsoft.NETCore.App 7.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
/// </summary>
private static Dictionary<string, RuntimeVersion> ParseRuntimes(IList<string> listed)
private static Dictionary<string, DotnetVersion> ParseRuntimes(IList<string> listed)
{
// Parse listed runtimes.
var runtimes = new Dictionary<string, RuntimeVersion>();
var runtimes = new Dictionary<string, DotnetVersion>();
var regex = RuntimeRegex();
listed.ForEach(r =>
{
var match = RuntimeRegex().Match(r);
var match = regex.Match(r);
if (match.Success)
{
runtimes.AddOrUpdateToLatest(match.Groups[1].Value, new RuntimeVersion(match.Groups[6].Value, match.Groups[2].Value, match.Groups[4].Value, match.Groups[5].Value));
runtimes.AddOrUpdateToLatest(match.Groups[1].Value, new DotnetVersion(match.Groups[6].Value, match.Groups[2].Value, match.Groups[4].Value, match.Groups[5].Value));
}
});
@@ -107,7 +56,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
/// <summary>
/// Returns a dictionary mapping runtimes to their newest version.
/// </summary>
internal Dictionary<string, RuntimeVersion> GetNewestRuntimes()
internal Dictionary<string, DotnetVersion> GetNewestRuntimes()
{
var listed = dotNet.GetListedRuntimes();
return ParseRuntimes(listed);

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
using Semmle.Util;
using System.Text.RegularExpressions;
using System.Linq;
namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal partial class Sdk
{
private readonly IDotNet dotNet;
public Sdk(IDotNet dotNet) => this.dotNet = dotNet;
[GeneratedRegex(@"^(\d+\.\d+\.\d+)(-([a-z]+)\.(\d+\.\d+\.\d+))?\s\[(.+)\]$")]
private static partial Regex SdkRegex();
private static HashSet<DotnetVersion> ParseSdks(IList<string> listed)
{
var sdks = new HashSet<DotnetVersion>();
var regex = SdkRegex();
listed.ForEach(r =>
{
var match = regex.Match(r);
if (match.Success)
{
sdks.Add(new DotnetVersion(match.Groups[5].Value, match.Groups[1].Value, match.Groups[3].Value, match.Groups[4].Value));
}
});
return sdks;
}
public DotnetVersion? GetNewestSdk()
{
var listed = dotNet.GetListedSdks();
var sdks = ParseSdks(listed);
return sdks.Max();
}
}
}

View File

@@ -1,7 +1,3 @@
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
namespace Semmle.Extraction.CSharp
{
/// <summary>

View File

@@ -1,5 +1,5 @@
using Microsoft.CodeAnalysis.CSharp;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CSharp

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Semmle.Extraction.CSharp.Entities;
using System.Collections.Generic;
using System.Linq;
namespace Semmle.Extraction.CSharp.Comments
{

View File

@@ -1,8 +1,8 @@
using Microsoft.CodeAnalysis;
using Semmle.Extraction.CSharp.Entities;
using Semmle.Util;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Semmle.Util;
using Semmle.Extraction.CSharp.Entities;
namespace Semmle.Extraction.CSharp
{

View File

@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,6 +1,5 @@
using Microsoft.CodeAnalysis;
using Semmle.Extraction.CSharp;
using System.IO;
using Microsoft.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,11 +1,10 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,6 +1,5 @@
using Semmle.Extraction.Entities;
using System.IO;
using System;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,7 +1,7 @@
using Microsoft.CodeAnalysis;
using System;
using System;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Entities

View File

@@ -1,11 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Util;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
using System.IO;
using System.Diagnostics.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,7 +1,7 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,5 +1,5 @@
using Microsoft.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,7 +1,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,5 +1,5 @@
using Microsoft.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.Kinds;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,6 +1,6 @@
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{

View File

@@ -1,7 +1,7 @@
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System;
using System.IO;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,11 +1,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Semmle.Util;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Util;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,8 +1,8 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; // lgtm[cs/similar-file]
using System.IO; // lgtm[cs/similar-file]
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,7 +1,7 @@
using System.IO;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,7 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System;
using System.IO;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; // lgtm[cs/similar-file]
using System.IO; // lgtm[cs/similar-file]
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,6 @@
using System.IO;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; // lgtm[cs/similar-file]
using System.IO; // lgtm[cs/similar-file]
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,6 @@
using System.IO;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{

View File

@@ -1,6 +1,5 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions

Some files were not shown because too many files have changed in this diff Show More