Merge branch 'main' into redsun82/rust-trait-path

This commit is contained in:
Paolo Tranquilli
2025-02-24 14:12:53 +01:00
16 changed files with 883 additions and 365 deletions

View File

@@ -49,11 +49,17 @@ predicate interestingConcatenation(DataFlow::Node incoming, DataFlow::Node outgo
call.getTarget() = op and
op.hasQualifiedName("std", "operator+") and
op.getType().(UserType).hasQualifiedName("std", "basic_string") and
incoming.asIndirectArgument() = call.getArgument(1) and // left operand
incoming.asIndirectArgument() = call.getArgument(1) and // right operand
call = outgoing.asInstruction().getUnconvertedResultExpression()
)
}
/**
* A state will represent the most recent concatenation that occurred in the data flow.
* - `TConcatState` if the concetenation has not yet occurred.
* - `TExecState(incoming, outgoing)`, representing the concatenation of data from `incoming`
* into result `outgoing`.
*/
newtype TState =
TConcatState() or
TExecState(DataFlow::Node incoming, DataFlow::Node outgoing) {
@@ -74,7 +80,9 @@ class ExecState extends TExecState {
DataFlow::Node getOutgoingNode() { result = outgoing }
/** Holds if this is a possible `ExecState` for `sink`. */
/**
* Holds if this is a possible `ExecState` at `sink`, that is, if `outgoing` flows to `sink`.
*/
predicate isFeasibleForSink(DataFlow::Node sink) { ExecState::flow(outgoing, sink) }
string toString() { result = "ExecState" }
@@ -110,6 +118,12 @@ module ExecStateConfig implements DataFlow::ConfigSig {
module ExecState = TaintTracking::Global<ExecStateConfig>;
/**
* A full `TaintTracking` configuration from source to concatenation to sink, using a flow
* state to remember the concatenation. It's important that we track flow to the sink even though
* as soon as we reach the concatenation we know it will get there (due to the check of
* `isFeasibleForSink`), because this way we get a complete flow path.
*/
module ExecTaintConfig implements DataFlow::StateConfigSig {
class FlowState = TState;

View File

@@ -7,68 +7,88 @@ edges
| test.cpp:47:21:47:26 | *call to getenv | test.cpp:50:35:50:43 | *envCflags | provenance | |
| test.cpp:50:11:50:17 | sprintf output argument | test.cpp:51:10:51:16 | *command | provenance | |
| test.cpp:50:35:50:43 | *envCflags | test.cpp:50:11:50:17 | sprintf output argument | provenance | Config |
| test.cpp:62:9:62:16 | fread output argument | test.cpp:64:20:64:27 | *filename | provenance | |
| test.cpp:64:11:64:17 | strncat output argument | test.cpp:65:10:65:16 | *command | provenance | |
| test.cpp:64:20:64:27 | *filename | test.cpp:64:11:64:17 | strncat output argument | provenance | Config |
| test.cpp:82:9:82:16 | fread output argument | test.cpp:84:20:84:27 | *filename | provenance | |
| test.cpp:84:11:84:17 | strncat output argument | test.cpp:85:32:85:38 | *command | provenance | |
| test.cpp:84:20:84:27 | *filename | test.cpp:84:11:84:17 | strncat output argument | provenance | Config |
| test.cpp:91:9:91:16 | fread output argument | test.cpp:93:17:93:24 | *filename | provenance | |
| test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | *path | provenance | |
| test.cpp:93:17:93:24 | *filename | test.cpp:93:11:93:14 | strncat output argument | provenance | Config |
| test.cpp:106:20:106:38 | *call to getenv | test.cpp:107:33:107:36 | *path | provenance | TaintFunction |
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:107:31:107:31 | call to operator+ | provenance | |
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | *call to c_str | provenance | TaintFunction |
| test.cpp:107:33:107:36 | *path | test.cpp:107:31:107:31 | call to operator+ | provenance | Config |
| test.cpp:113:20:113:38 | *call to getenv | test.cpp:114:19:114:22 | *path | provenance | TaintFunction |
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | *call to c_str | provenance | TaintFunction |
| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | *call to c_str | provenance | TaintFunction |
| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:10:114:23 | call to operator+ | provenance | |
| test.cpp:114:19:114:22 | *path | test.cpp:114:10:114:23 | call to operator+ | provenance | Config |
| test.cpp:114:19:114:22 | *path | test.cpp:114:17:114:17 | call to operator+ | provenance | Config |
| test.cpp:119:20:119:38 | *call to getenv | test.cpp:120:19:120:22 | *path | provenance | TaintFunction |
| test.cpp:120:17:120:17 | call to operator+ | test.cpp:120:10:120:30 | *call to data | provenance | TaintFunction |
| test.cpp:120:19:120:22 | *path | test.cpp:120:17:120:17 | call to operator+ | provenance | Config |
| test.cpp:140:9:140:11 | fread output argument | test.cpp:142:31:142:33 | *str | provenance | |
| test.cpp:142:11:142:17 | sprintf output argument | test.cpp:143:10:143:16 | *command | provenance | |
| test.cpp:142:31:142:33 | *str | test.cpp:142:11:142:17 | sprintf output argument | provenance | Config |
| test.cpp:174:9:174:16 | fread output argument | test.cpp:177:20:177:27 | *filename | provenance | |
| test.cpp:174:9:174:16 | fread output argument | test.cpp:180:22:180:29 | *filename | provenance | |
| test.cpp:177:13:177:17 | strncat output argument | test.cpp:178:22:178:26 | *flags | provenance | |
| test.cpp:177:13:177:17 | strncat output argument | test.cpp:178:22:178:26 | *flags | provenance | |
| test.cpp:177:20:177:27 | *filename | test.cpp:177:13:177:17 | strncat output argument | provenance | Config |
| test.cpp:177:20:177:27 | *filename | test.cpp:177:13:177:17 | strncat output argument | provenance | TaintFunction |
| test.cpp:178:13:178:19 | strncat output argument | test.cpp:183:32:183:38 | *command | provenance | |
| test.cpp:178:13:178:19 | strncat output argument | test.cpp:183:32:183:38 | *command | provenance | |
| test.cpp:178:22:178:26 | *flags | test.cpp:178:13:178:19 | strncat output argument | provenance | Config |
| test.cpp:178:22:178:26 | *flags | test.cpp:178:13:178:19 | strncat output argument | provenance | TaintFunction |
| test.cpp:180:13:180:19 | strncat output argument | test.cpp:183:32:183:38 | *command | provenance | |
| test.cpp:180:22:180:29 | *filename | test.cpp:180:13:180:19 | strncat output argument | provenance | Config |
| test.cpp:186:47:186:54 | *filename | test.cpp:187:18:187:25 | *filename | provenance | |
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:20:188:24 | *flags | provenance | |
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:20:188:24 | *flags | provenance | |
| test.cpp:187:18:187:25 | *filename | test.cpp:187:11:187:15 | strncat output argument | provenance | Config |
| test.cpp:187:18:187:25 | *filename | test.cpp:187:11:187:15 | strncat output argument | provenance | TaintFunction |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command | provenance | |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command | provenance | |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command [Return] | provenance | |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command [Return] | provenance | |
| test.cpp:188:20:188:24 | *flags | test.cpp:188:11:188:17 | strncat output argument | provenance | Config |
| test.cpp:188:20:188:24 | *flags | test.cpp:188:11:188:17 | strncat output argument | provenance | TaintFunction |
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | *filename | provenance | |
| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | *command | provenance | |
| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | *command | provenance | |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | provenance | |
| test.cpp:196:26:196:33 | *filename | test.cpp:196:10:196:16 | concat output argument | provenance | Config |
| test.cpp:196:26:196:33 | *filename | test.cpp:196:10:196:16 | concat output argument | provenance | TaintFunction |
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | *filename | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:220:10:220:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:220:10:220:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:19:220:26 | *filename | test.cpp:220:10:220:16 | strncat output argument | provenance | Config |
| test.cpp:220:19:220:26 | *filename | test.cpp:220:10:220:16 | strncat output argument | provenance | Config |
| test.cpp:220:19:220:26 | *filename | test.cpp:220:19:220:26 | *filename | provenance | |
| test.cpp:63:9:63:16 | fread output argument | test.cpp:65:20:65:27 | *filename | provenance | |
| test.cpp:65:11:65:17 | strncat output argument | test.cpp:66:10:66:16 | *command | provenance | |
| test.cpp:65:20:65:27 | *filename | test.cpp:65:11:65:17 | strncat output argument | provenance | Config |
| test.cpp:83:9:83:16 | fread output argument | test.cpp:85:20:85:27 | *filename | provenance | |
| test.cpp:85:11:85:17 | strncat output argument | test.cpp:86:32:86:38 | *command | provenance | |
| test.cpp:85:20:85:27 | *filename | test.cpp:85:11:85:17 | strncat output argument | provenance | Config |
| test.cpp:92:9:92:16 | fread output argument | test.cpp:94:17:94:24 | *filename | provenance | |
| test.cpp:94:11:94:14 | strncat output argument | test.cpp:95:45:95:48 | *path | provenance | |
| test.cpp:94:17:94:24 | *filename | test.cpp:94:11:94:14 | strncat output argument | provenance | Config |
| test.cpp:107:20:107:38 | *call to getenv | test.cpp:108:33:108:36 | *path | provenance | TaintFunction |
| test.cpp:108:31:108:31 | call to operator+ | test.cpp:108:31:108:31 | call to operator+ | provenance | |
| test.cpp:108:31:108:31 | call to operator+ | test.cpp:109:18:109:22 | *call to c_str | provenance | TaintFunction |
| test.cpp:108:33:108:36 | *path | test.cpp:108:31:108:31 | call to operator+ | provenance | Config |
| test.cpp:114:20:114:38 | *call to getenv | test.cpp:115:19:115:22 | *path | provenance | TaintFunction |
| test.cpp:115:10:115:23 | call to operator+ | test.cpp:115:25:115:29 | *call to c_str | provenance | TaintFunction |
| test.cpp:115:10:115:23 | call to operator+ | test.cpp:115:25:115:29 | *call to c_str | provenance | TaintFunction |
| test.cpp:115:17:115:17 | call to operator+ | test.cpp:115:10:115:23 | call to operator+ | provenance | |
| test.cpp:115:19:115:22 | *path | test.cpp:115:10:115:23 | call to operator+ | provenance | Config |
| test.cpp:115:19:115:22 | *path | test.cpp:115:17:115:17 | call to operator+ | provenance | Config |
| test.cpp:120:20:120:38 | *call to getenv | test.cpp:121:19:121:22 | *path | provenance | TaintFunction |
| test.cpp:121:17:121:17 | call to operator+ | test.cpp:121:10:121:30 | *call to data | provenance | TaintFunction |
| test.cpp:121:19:121:22 | *path | test.cpp:121:17:121:17 | call to operator+ | provenance | Config |
| test.cpp:141:9:141:11 | fread output argument | test.cpp:143:31:143:33 | *str | provenance | |
| test.cpp:143:11:143:17 | sprintf output argument | test.cpp:144:10:144:16 | *command | provenance | |
| test.cpp:143:31:143:33 | *str | test.cpp:143:11:143:17 | sprintf output argument | provenance | Config |
| test.cpp:175:9:175:16 | fread output argument | test.cpp:178:20:178:27 | *filename | provenance | |
| test.cpp:175:9:175:16 | fread output argument | test.cpp:181:22:181:29 | *filename | provenance | |
| test.cpp:178:13:178:17 | strncat output argument | test.cpp:179:22:179:26 | *flags | provenance | |
| test.cpp:178:13:178:17 | strncat output argument | test.cpp:179:22:179:26 | *flags | provenance | |
| test.cpp:178:20:178:27 | *filename | test.cpp:178:13:178:17 | strncat output argument | provenance | Config |
| test.cpp:178:20:178:27 | *filename | test.cpp:178:13:178:17 | strncat output argument | provenance | TaintFunction |
| test.cpp:179:13:179:19 | strncat output argument | test.cpp:184:32:184:38 | *command | provenance | |
| test.cpp:179:13:179:19 | strncat output argument | test.cpp:184:32:184:38 | *command | provenance | |
| test.cpp:179:22:179:26 | *flags | test.cpp:179:13:179:19 | strncat output argument | provenance | Config |
| test.cpp:179:22:179:26 | *flags | test.cpp:179:13:179:19 | strncat output argument | provenance | TaintFunction |
| test.cpp:181:13:181:19 | strncat output argument | test.cpp:184:32:184:38 | *command | provenance | |
| test.cpp:181:22:181:29 | *filename | test.cpp:181:13:181:19 | strncat output argument | provenance | Config |
| test.cpp:187:47:187:54 | *filename | test.cpp:188:18:188:25 | *filename | provenance | |
| test.cpp:188:11:188:15 | strncat output argument | test.cpp:189:20:189:24 | *flags | provenance | |
| test.cpp:188:11:188:15 | strncat output argument | test.cpp:189:20:189:24 | *flags | provenance | |
| test.cpp:188:18:188:25 | *filename | test.cpp:188:11:188:15 | strncat output argument | provenance | Config |
| test.cpp:188:18:188:25 | *filename | test.cpp:188:11:188:15 | strncat output argument | provenance | TaintFunction |
| test.cpp:189:11:189:17 | strncat output argument | test.cpp:187:19:187:25 | *command | provenance | |
| test.cpp:189:11:189:17 | strncat output argument | test.cpp:187:19:187:25 | *command | provenance | |
| test.cpp:189:11:189:17 | strncat output argument | test.cpp:187:19:187:25 | *command [Return] | provenance | |
| test.cpp:189:11:189:17 | strncat output argument | test.cpp:187:19:187:25 | *command [Return] | provenance | |
| test.cpp:189:20:189:24 | *flags | test.cpp:189:11:189:17 | strncat output argument | provenance | Config |
| test.cpp:189:20:189:24 | *flags | test.cpp:189:11:189:17 | strncat output argument | provenance | TaintFunction |
| test.cpp:195:9:195:16 | fread output argument | test.cpp:197:26:197:33 | *filename | provenance | |
| test.cpp:197:10:197:16 | concat output argument | test.cpp:199:32:199:38 | *command | provenance | |
| test.cpp:197:10:197:16 | concat output argument | test.cpp:199:32:199:38 | *command | provenance | |
| test.cpp:197:26:197:33 | *filename | test.cpp:187:47:187:54 | *filename | provenance | |
| test.cpp:197:26:197:33 | *filename | test.cpp:197:10:197:16 | concat output argument | provenance | Config |
| test.cpp:197:26:197:33 | *filename | test.cpp:197:10:197:16 | concat output argument | provenance | TaintFunction |
| test.cpp:219:9:219:16 | fread output argument | test.cpp:221:19:221:26 | *filename | provenance | |
| test.cpp:221:10:221:16 | strncat output argument | test.cpp:221:10:221:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:221:10:221:16 | strncat output argument | test.cpp:221:10:221:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:221:10:221:16 | strncat output argument | test.cpp:223:32:223:38 | *command | provenance | |
| test.cpp:221:10:221:16 | strncat output argument | test.cpp:223:32:223:38 | *command | provenance | |
| test.cpp:221:19:221:26 | *filename | test.cpp:221:10:221:16 | strncat output argument | provenance | Config |
| test.cpp:221:19:221:26 | *filename | test.cpp:221:10:221:16 | strncat output argument | provenance | Config |
| test.cpp:221:19:221:26 | *filename | test.cpp:221:19:221:26 | *filename | provenance | |
| test.cpp:231:11:231:16 | strncat output argument | test.cpp:232:11:232:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:231:19:231:33 | *call to getenv | test.cpp:231:11:231:16 | strncat output argument | provenance | Config |
| test.cpp:232:11:232:16 | strncat output argument | test.cpp:233:11:233:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:232:11:232:16 | strncat output argument | test.cpp:233:11:233:16 | strncat output argument | provenance | TaintFunction |
| test.cpp:232:19:232:33 | *call to getenv | test.cpp:232:11:232:16 | strncat output argument | provenance | Config |
| test.cpp:233:11:233:16 | strncat output argument | test.cpp:234:10:234:15 | *buffer | provenance | |
| test.cpp:233:11:233:16 | strncat output argument | test.cpp:234:10:234:15 | *buffer | provenance | |
| test.cpp:242:11:242:17 | sprintf output argument | test.cpp:247:5:247:11 | *buffer1 | provenance | |
| test.cpp:242:11:242:17 | sprintf output argument | test.cpp:247:5:247:11 | *buffer1 | provenance | |
| test.cpp:243:5:243:10 | *call to getenv | test.cpp:242:11:242:17 | sprintf output argument | provenance | TaintFunction |
| test.cpp:244:5:244:10 | *call to getenv | test.cpp:242:11:242:17 | sprintf output argument | provenance | Config |
| test.cpp:244:5:244:10 | *call to getenv | test.cpp:242:11:242:17 | sprintf output argument | provenance | TaintFunction |
| test.cpp:245:11:245:17 | sprintf output argument | test.cpp:249:10:249:16 | *buffer2 | provenance | |
| test.cpp:245:11:245:17 | sprintf output argument | test.cpp:249:10:249:16 | *buffer2 | provenance | |
| test.cpp:245:11:245:17 | sprintf output argument | test.cpp:249:10:249:16 | *buffer2 | provenance | |
| test.cpp:247:5:247:11 | *buffer1 | test.cpp:245:11:245:17 | sprintf output argument | provenance | Config |
| test.cpp:247:5:247:11 | *buffer1 | test.cpp:245:11:245:17 | sprintf output argument | provenance | TaintFunction |
| test.cpp:248:5:248:10 | *call to getenv | test.cpp:245:11:245:17 | sprintf output argument | provenance | Config |
| test.cpp:259:13:259:18 | strncat output argument | test.cpp:261:10:261:15 | *buffer | provenance | |
| test.cpp:259:21:259:35 | *call to getenv | test.cpp:259:13:259:18 | strncat output argument | provenance | Config |
nodes
| test.cpp:15:27:15:30 | **argv | semmle.label | **argv |
| test.cpp:16:20:16:26 | *access to array | semmle.label | *access to array |
@@ -80,98 +100,130 @@ nodes
| test.cpp:50:11:50:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:50:35:50:43 | *envCflags | semmle.label | *envCflags |
| test.cpp:51:10:51:16 | *command | semmle.label | *command |
| test.cpp:62:9:62:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:64:11:64:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:64:20:64:27 | *filename | semmle.label | *filename |
| test.cpp:65:10:65:16 | *command | semmle.label | *command |
| test.cpp:82:9:82:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:84:11:84:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:84:20:84:27 | *filename | semmle.label | *filename |
| test.cpp:85:32:85:38 | *command | semmle.label | *command |
| test.cpp:91:9:91:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:93:11:93:14 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:93:17:93:24 | *filename | semmle.label | *filename |
| test.cpp:94:45:94:48 | *path | semmle.label | *path |
| test.cpp:106:20:106:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:107:33:107:36 | *path | semmle.label | *path |
| test.cpp:108:18:108:22 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:113:20:113:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:114:17:114:17 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:114:19:114:22 | *path | semmle.label | *path |
| test.cpp:114:25:114:29 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:114:25:114:29 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:119:20:119:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:120:10:120:30 | *call to data | semmle.label | *call to data |
| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:120:19:120:22 | *path | semmle.label | *path |
| test.cpp:140:9:140:11 | fread output argument | semmle.label | fread output argument |
| test.cpp:142:11:142:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:142:31:142:33 | *str | semmle.label | *str |
| test.cpp:143:10:143:16 | *command | semmle.label | *command |
| test.cpp:174:9:174:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:177:13:177:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:177:13:177:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:177:20:177:27 | *filename | semmle.label | *filename |
| test.cpp:178:13:178:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:178:13:178:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:178:22:178:26 | *flags | semmle.label | *flags |
| test.cpp:178:22:178:26 | *flags | semmle.label | *flags |
| test.cpp:180:13:180:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:180:22:180:29 | *filename | semmle.label | *filename |
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:186:19:186:25 | *command | semmle.label | *command |
| test.cpp:186:19:186:25 | *command | semmle.label | *command |
| test.cpp:186:19:186:25 | *command [Return] | semmle.label | *command [Return] |
| test.cpp:186:19:186:25 | *command [Return] | semmle.label | *command [Return] |
| test.cpp:186:47:186:54 | *filename | semmle.label | *filename |
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:187:18:187:25 | *filename | semmle.label | *filename |
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:188:20:188:24 | *flags | semmle.label | *flags |
| test.cpp:188:20:188:24 | *flags | semmle.label | *flags |
| test.cpp:194:9:194:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:196:10:196:16 | concat output argument | semmle.label | concat output argument |
| test.cpp:196:10:196:16 | concat output argument | semmle.label | concat output argument |
| test.cpp:196:26:196:33 | *filename | semmle.label | *filename |
| test.cpp:198:32:198:38 | *command | semmle.label | *command |
| test.cpp:198:32:198:38 | *command | semmle.label | *command |
| test.cpp:218:9:218:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:220:19:220:26 | *filename | semmle.label | *filename |
| test.cpp:220:19:220:26 | *filename | semmle.label | *filename |
| test.cpp:222:32:222:38 | *command | semmle.label | *command |
| test.cpp:222:32:222:38 | *command | semmle.label | *command |
| test.cpp:63:9:63:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:65:11:65:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:65:20:65:27 | *filename | semmle.label | *filename |
| test.cpp:66:10:66:16 | *command | semmle.label | *command |
| test.cpp:83:9:83:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:85:11:85:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:85:20:85:27 | *filename | semmle.label | *filename |
| test.cpp:86:32:86:38 | *command | semmle.label | *command |
| test.cpp:92:9:92:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:94:11:94:14 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:94:17:94:24 | *filename | semmle.label | *filename |
| test.cpp:95:45:95:48 | *path | semmle.label | *path |
| test.cpp:107:20:107:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:108:31:108:31 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:108:31:108:31 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:108:33:108:36 | *path | semmle.label | *path |
| test.cpp:109:18:109:22 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:114:20:114:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:115:10:115:23 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:115:10:115:23 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:115:17:115:17 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:115:19:115:22 | *path | semmle.label | *path |
| test.cpp:115:25:115:29 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:115:25:115:29 | *call to c_str | semmle.label | *call to c_str |
| test.cpp:120:20:120:38 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:121:10:121:30 | *call to data | semmle.label | *call to data |
| test.cpp:121:17:121:17 | call to operator+ | semmle.label | call to operator+ |
| test.cpp:121:19:121:22 | *path | semmle.label | *path |
| test.cpp:141:9:141:11 | fread output argument | semmle.label | fread output argument |
| test.cpp:143:11:143:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:143:31:143:33 | *str | semmle.label | *str |
| test.cpp:144:10:144:16 | *command | semmle.label | *command |
| test.cpp:175:9:175:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:178:13:178:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:178:13:178:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:178:20:178:27 | *filename | semmle.label | *filename |
| test.cpp:179:13:179:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:179:13:179:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:179:22:179:26 | *flags | semmle.label | *flags |
| test.cpp:179:22:179:26 | *flags | semmle.label | *flags |
| test.cpp:181:13:181:19 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:181:22:181:29 | *filename | semmle.label | *filename |
| test.cpp:184:32:184:38 | *command | semmle.label | *command |
| test.cpp:184:32:184:38 | *command | semmle.label | *command |
| test.cpp:184:32:184:38 | *command | semmle.label | *command |
| test.cpp:187:19:187:25 | *command | semmle.label | *command |
| test.cpp:187:19:187:25 | *command | semmle.label | *command |
| test.cpp:187:19:187:25 | *command [Return] | semmle.label | *command [Return] |
| test.cpp:187:19:187:25 | *command [Return] | semmle.label | *command [Return] |
| test.cpp:187:47:187:54 | *filename | semmle.label | *filename |
| test.cpp:188:11:188:15 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:188:11:188:15 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:188:18:188:25 | *filename | semmle.label | *filename |
| test.cpp:189:11:189:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:189:11:189:17 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:189:20:189:24 | *flags | semmle.label | *flags |
| test.cpp:189:20:189:24 | *flags | semmle.label | *flags |
| test.cpp:195:9:195:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:197:10:197:16 | concat output argument | semmle.label | concat output argument |
| test.cpp:197:10:197:16 | concat output argument | semmle.label | concat output argument |
| test.cpp:197:26:197:33 | *filename | semmle.label | *filename |
| test.cpp:199:32:199:38 | *command | semmle.label | *command |
| test.cpp:199:32:199:38 | *command | semmle.label | *command |
| test.cpp:219:9:219:16 | fread output argument | semmle.label | fread output argument |
| test.cpp:221:10:221:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:221:10:221:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:221:10:221:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:221:10:221:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:221:19:221:26 | *filename | semmle.label | *filename |
| test.cpp:221:19:221:26 | *filename | semmle.label | *filename |
| test.cpp:223:32:223:38 | *command | semmle.label | *command |
| test.cpp:223:32:223:38 | *command | semmle.label | *command |
| test.cpp:231:11:231:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:231:19:231:33 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:232:11:232:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:232:11:232:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:232:19:232:33 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:233:11:233:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:233:11:233:16 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:234:10:234:15 | *buffer | semmle.label | *buffer |
| test.cpp:234:10:234:15 | *buffer | semmle.label | *buffer |
| test.cpp:242:11:242:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:242:11:242:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:243:5:243:10 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:244:5:244:10 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:245:11:245:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:245:11:245:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:245:11:245:17 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:247:5:247:11 | *buffer1 | semmle.label | *buffer1 |
| test.cpp:247:5:247:11 | *buffer1 | semmle.label | *buffer1 |
| test.cpp:248:5:248:10 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:249:10:249:16 | *buffer2 | semmle.label | *buffer2 |
| test.cpp:249:10:249:16 | *buffer2 | semmle.label | *buffer2 |
| test.cpp:249:10:249:16 | *buffer2 | semmle.label | *buffer2 |
| test.cpp:259:13:259:18 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:259:21:259:35 | *call to getenv | semmle.label | *call to getenv |
| test.cpp:261:10:261:15 | *buffer | semmle.label | *buffer |
subpaths
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command [Return] | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command [Return] | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:197:26:197:33 | *filename | test.cpp:187:47:187:54 | *filename | test.cpp:187:19:187:25 | *command | test.cpp:197:10:197:16 | concat output argument |
| test.cpp:197:26:197:33 | *filename | test.cpp:187:47:187:54 | *filename | test.cpp:187:19:187:25 | *command | test.cpp:197:10:197:16 | concat output argument |
| test.cpp:197:26:197:33 | *filename | test.cpp:187:47:187:54 | *filename | test.cpp:187:19:187:25 | *command [Return] | test.cpp:197:10:197:16 | concat output argument |
| test.cpp:197:26:197:33 | *filename | test.cpp:187:47:187:54 | *filename | test.cpp:187:19:187:25 | *command [Return] | test.cpp:197:10:197:16 | concat output argument |
#select
| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | **argv | test.cpp:23:12:23:19 | *command1 | 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 | 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 | test.cpp:51:10:51:16 | *command | 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 | 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 | 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 | 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 |
| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | *path | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument |
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | *call to getenv | test.cpp:108:18:108:22 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | *call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | *call to getenv | test.cpp:114:25:114:29 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | *call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ |
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | *call to getenv | test.cpp:114:25:114:29 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | *call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | *call to getenv | test.cpp:120:10:120:30 | *call to data | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | *call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument |
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument |
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:178:13:178:19 | strncat output argument | strncat output argument |
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:180:13:180:19 | strncat output argument | strncat output argument |
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (string read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument |
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (string read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument |
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (string read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (string read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
| test.cpp:66:10:66:16 | command | test.cpp:63:9:63:16 | fread output argument | test.cpp:66:10:66:16 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:63:9:63:16 | fread output argument | user input (string read by fread) | test.cpp:65:11:65:17 | strncat output argument | strncat output argument |
| test.cpp:86:32:86:38 | command | test.cpp:83:9:83:16 | fread output argument | test.cpp:86:32:86:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:83:9:83:16 | fread output argument | user input (string read by fread) | test.cpp:85:11:85:17 | strncat output argument | strncat output argument |
| test.cpp:95:45:95:48 | path | test.cpp:92:9:92:16 | fread output argument | test.cpp:95:45:95:48 | *path | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:92:9:92:16 | fread output argument | user input (string read by fread) | test.cpp:94:11:94:14 | strncat output argument | strncat output argument |
| test.cpp:109:18:109:22 | call to c_str | test.cpp:107:20:107:38 | *call to getenv | test.cpp:109:18:109:22 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:107:20:107:38 | *call to getenv | user input (an environment variable) | test.cpp:108:31:108:31 | call to operator+ | call to operator+ |
| test.cpp:115:25:115:29 | call to c_str | test.cpp:114:20:114:38 | *call to getenv | test.cpp:115:25:115:29 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:114:20:114:38 | *call to getenv | user input (an environment variable) | test.cpp:115:10:115:23 | call to operator+ | call to operator+ |
| test.cpp:115:25:115:29 | call to c_str | test.cpp:114:20:114:38 | *call to getenv | test.cpp:115:25:115:29 | *call to c_str | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:114:20:114:38 | *call to getenv | user input (an environment variable) | test.cpp:115:17:115:17 | call to operator+ | call to operator+ |
| test.cpp:121:25:121:28 | call to data | test.cpp:120:20:120:38 | *call to getenv | test.cpp:121:10:121:30 | *call to data | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:120:20:120:38 | *call to getenv | user input (an environment variable) | test.cpp:121:17:121:17 | call to operator+ | call to operator+ |
| test.cpp:144:10:144:16 | command | test.cpp:141:9:141:11 | fread output argument | test.cpp:144:10:144:16 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:141:9:141:11 | fread output argument | user input (string read by fread) | test.cpp:143:11:143:17 | sprintf output argument | sprintf output argument |
| test.cpp:184:32:184:38 | command | test.cpp:175:9:175:16 | fread output argument | test.cpp:184:32:184:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:175:9:175:16 | fread output argument | user input (string read by fread) | test.cpp:178:13:178:17 | strncat output argument | strncat output argument |
| test.cpp:184:32:184:38 | command | test.cpp:175:9:175:16 | fread output argument | test.cpp:184:32:184:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:175:9:175:16 | fread output argument | user input (string read by fread) | test.cpp:179:13:179:19 | strncat output argument | strncat output argument |
| test.cpp:184:32:184:38 | command | test.cpp:175:9:175:16 | fread output argument | test.cpp:184:32:184:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:175:9:175:16 | fread output argument | user input (string read by fread) | test.cpp:181:13:181:19 | strncat output argument | strncat output argument |
| test.cpp:199:32:199:38 | command | test.cpp:195:9:195:16 | fread output argument | test.cpp:199:32:199:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:195:9:195:16 | fread output argument | user input (string read by fread) | test.cpp:188:11:188:15 | strncat output argument | strncat output argument |
| test.cpp:199:32:199:38 | command | test.cpp:195:9:195:16 | fread output argument | test.cpp:199:32:199:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:195:9:195:16 | fread output argument | user input (string read by fread) | test.cpp:189:11:189:17 | strncat output argument | strncat output argument |
| test.cpp:223:32:223:38 | command | test.cpp:219:9:219:16 | fread output argument | test.cpp:223:32:223:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:219:9:219:16 | fread output argument | user input (string read by fread) | test.cpp:221:10:221:16 | strncat output argument | strncat output argument |
| test.cpp:223:32:223:38 | command | test.cpp:219:9:219:16 | fread output argument | test.cpp:223:32:223:38 | *command | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:219:9:219:16 | fread output argument | user input (string read by fread) | test.cpp:221:10:221:16 | strncat output argument | strncat output argument |
| test.cpp:234:10:234:15 | buffer | test.cpp:231:19:231:33 | *call to getenv | test.cpp:234:10:234:15 | *buffer | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:231:19:231:33 | *call to getenv | user input (an environment variable) | test.cpp:231:11:231:16 | strncat output argument | strncat output argument |
| test.cpp:234:10:234:15 | buffer | test.cpp:232:19:232:33 | *call to getenv | test.cpp:234:10:234:15 | *buffer | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:232:19:232:33 | *call to getenv | user input (an environment variable) | test.cpp:232:11:232:16 | strncat output argument | strncat output argument |
| test.cpp:249:10:249:16 | buffer2 | test.cpp:243:5:243:10 | *call to getenv | test.cpp:249:10:249:16 | *buffer2 | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:243:5:243:10 | *call to getenv | user input (an environment variable) | test.cpp:245:11:245:17 | sprintf output argument | sprintf output argument |
| test.cpp:249:10:249:16 | buffer2 | test.cpp:244:5:244:10 | *call to getenv | test.cpp:249:10:249:16 | *buffer2 | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:244:5:244:10 | *call to getenv | user input (an environment variable) | test.cpp:242:11:242:17 | sprintf output argument | sprintf output argument |
| test.cpp:249:10:249:16 | buffer2 | test.cpp:244:5:244:10 | *call to getenv | test.cpp:249:10:249:16 | *buffer2 | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:244:5:244:10 | *call to getenv | user input (an environment variable) | test.cpp:245:11:245:17 | sprintf output argument | sprintf output argument |
| test.cpp:249:10:249:16 | buffer2 | test.cpp:248:5:248:10 | *call to getenv | test.cpp:249:10:249:16 | *buffer2 | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:248:5:248:10 | *call to getenv | user input (an environment variable) | test.cpp:245:11:245:17 | sprintf output argument | sprintf output argument |
| test.cpp:261:10:261:15 | buffer | test.cpp:259:21:259:35 | *call to getenv | test.cpp:261:10:261:15 | *buffer | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:259:21:259:35 | *call to getenv | user input (an environment variable) | test.cpp:259:13:259:18 | strncat output argument | strncat output argument |

View File

@@ -14,7 +14,7 @@ extern void encodeShellString(char *shellStr, int maxChars, const char* cStr);
int main(int argc, char** argv) {
char *userName = argv[2];
{
// BAD: a string from the user is injected directly into
// a command.
@@ -23,10 +23,10 @@ int main(int argc, char** argv) {
system(command1);
}
{
{
// GOOD: the user string is encoded by a library routine.
char userNameQuoted[1000] = {0};
encodeShellString(userNameQuoted, 1000, userName);
encodeShellString(userNameQuoted, 1000, userName);
char command2[1000] = {0};
sprintf(command2, "userinfo -v %s", userNameQuoted);
system(command2);
@@ -36,16 +36,16 @@ int main(int argc, char** argv) {
void test2(char* arg2) {
// GOOD?: the user string is the *first* part of the command, like $CC in many environments
char *envCC = getenv("CC");
char command[1000];
sprintf("%s %s", envCC, arg2);
sprintf(command, "%s %s", envCC, arg2);
system(command);
}
void test3(char* arg1) {
// GOOD?: the user string is a `$CFLAGS` environment variable
char *envCflags = getenv("CFLAGS");
char command[1000];
sprintf(command, "%s %s", arg1, envCflags);
system(command);
@@ -54,6 +54,7 @@ void test3(char* arg1) {
typedef unsigned long size_t;
typedef void FILE;
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
char *strncpy(char *s1, const char *s2, size_t n);
char *strncat(char *s1, const char *s2, size_t n);
void test4(FILE *f) {
@@ -160,7 +161,7 @@ void test15(FILE *f) {
fread(temp, 1, 10, f);
int x = atoi(temp);
char temp2[10];
sprintf(temp2, "%d", x);
sprintf(command, "tail -n %s foo.log", temp2);
@@ -222,4 +223,42 @@ void test19(FILE *f) {
execl("/bin/sh", "sh", "-c", command);
}
void test20() {
// BAD: the user strings `var_b`, `var_c` are injected directly into a command
char buffer[1024 * 4];
strncpy(buffer, getenv("var_a"), 1024);
strncat(buffer, getenv("var_b"), 1024);
strncat(buffer, getenv("var_c"), 1024);
strncat(buffer, " ", 1024);
system(buffer);
}
void test21() {
// BAD: the user strings `var_b`, `var_c` are injected directly into a command
char buffer1[1024];
char buffer2[1024];
sprintf(buffer1, "%s %s",
getenv("var_a"),
getenv("var_b"));
sprintf(buffer2, "%s %s %s",
" ",
buffer1,
getenv("var_c"));
system(buffer2);
}
void test22() {
// BAD: the user strings `var_a` are injected directly into a command
char buffer[1024 * 11];
int i;
strncpy(buffer, "command ", 1024);
for (i = 0; i < 10; i++) {
strncat(buffer, getenv("var_a"), 1024);
}
system(buffer);
}
// open question: do we want to report certain sources even when they're the start of the string?

View File

@@ -0,0 +1,165 @@
.. _codeql-cli-2.20.5:
==========================
CodeQL 2.20.5 (2025-02-20)
==========================
.. contents:: Contents
:depth: 2
:local:
:backlinks: none
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
Security Coverage
-----------------
CodeQL 2.20.5 runs a total of 450 security queries when configured with the Default suite (covering 168 CWE). The Extended suite enables an additional 136 queries (covering 34 more CWE). 4 security queries have been added with this release.
CodeQL CLI
----------
Breaking Changes
~~~~~~~~~~~~~~~~
* Removed support for :code:`QlBuiltins::BigInt`\ s in the :code:`avg()` aggregate.
* A number of breaking changes have been made to the C and C++ CodeQL test environment as used by :code:`codeql test run`\ :
* The :code:`-Xclang-only=<arg>` option is no longer supported by :code:`semmle-extractor-options`. Instead, when either :code:`--clang` or :code:`--clang_version` is specified the option should be replaced by :code:`<arg>` only, otherwise the option should be omitted.
* The :code:`--sys_include <arg>` and :code:`--preinclude <arg>` options are no longer supported by :code:`semmle-extractor-options`. Instead, :code:`--edg <option_name> --edg <arg>` should be specified.
* The :code:`-idirafter <arg>` option is no longer supported by :code:`semmle-extractor-options`. Instead, :code:`--edg --sys_include --edg <arg>` should be specified.
* The :code:`-imacros <arg>` option is no longer supported by :code:`semmle-extractor-options`. Instead, :code:`--edg --preinclude_macros --edg <arg>` should be specified.
* The :code:`/FI <arg>` option is no longer supported by :code:`semmle-extractor-options`. Instead, :code:`--edg --preinclude --edg <arg>` should be specified.
* The :code:`-Wreserved-user-defined-literal`, :code:`-Wno-reserved-user-defined-literal`, :code:`-fwritable-strings`, :code:`/Zc:rvalueCast`, :code:`/Zc:rvalueCast-`, and :code:`/Zc:wchar_t-` options are no longer supported by :code:`semmle-extractor-options`. Instead, :code:`--edg --reserved_user_defined_literal`, :code:`--edg --no-reserved_user_defined_literal`, :code:`--edg --no_const_string_literals`, :code:`--edg --no_preserve_lvalues_with_same_type_casts`, :code:`--edg --preserve_lvalues_with_same_type_casts`, and :code:`--edg --no_wchar_t_keyword` should be specified, respectively.
* The :code:`/Fo <arg>` option is no longer supported by :code:`semmle-extractor-options`. The option should be omitted.
Query Packs
-----------
Bug Fixes
~~~~~~~~~
JavaScript/TypeScript
"""""""""""""""""""""
* Fixed a recently-introduced bug that prevented taint tracking through :code:`URLSearchParams` objects.
The original behaviour has been restored and taint should once again be tracked through such objects.
* Fixed a rare issue that would occur when a function declaration inside a block statement was referenced before it was declared.
Such code is reliant on legacy web semantics, which is non-standard but nevertheless implemented by most engines.
CodeQL now takes legacy web semantics into account and resolves references to these functions correctly.
* Fixed a bug that would cause parse errors in :code:`.jsx` files in rare cases where the file contained syntax that was misinterpreted as Flow syntax.
Breaking Changes
~~~~~~~~~~~~~~~~
GitHub Actions
""""""""""""""
* The following queries have been removed from the :code:`code-scanning` and :code:`security-extended` suites.
Any existing alerts for these queries will be closed automatically.
* :code:`actions/if-expression-always-true/critical`
* :code:`actions/if-expression-always-true/high`
* :code:`actions/unnecessary-use-of-advanced-config`
* The following query has been moved from the :code:`code-scanning` suite to the :code:`security-extended` suite. Any existing alerts for this query will be closed automatically unless the analysis is configured to use the :code:`security-extended` suite.
* :code:`actions/unpinned-tag`
* The following queries have been added to the :code:`security-extended` suite.
* :code:`actions/unversioned-immutable-action`
* :code:`actions/envpath-injection/medium`
* :code:`actions/envvar-injection/medium`
* :code:`actions/code-injection/medium`
* :code:`actions/artifact-poisoning/medium`
* :code:`actions/untrusted-checkout/medium`
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Golang
""""""
* Added `github.com/gorilla/mux.Vars <https://pkg.go.dev/github.com/gorilla/mux#Vars>`__ to path sanitizers (disabled if `github.com/gorilla/mix.Router.SkipClean <https://pkg.go.dev/github.com/gorilla/mux#Router.SkipClean>`__ has been called).
GitHub Actions
""""""""""""""
* Fixed false positives in the query :code:`actions/unpinned-tag` (CWE-829), which will no longer flag uses of Docker-based GitHub actions pinned by the container's SHA256 digest.
New Queries
~~~~~~~~~~~
Java/Kotlin
"""""""""""
* Added a new query, :code:`java/csrf-unprotected-request-type`, to detect Cross-Site Request Forgery (CSRF) vulnerabilities due to using HTTP request types that are not default-protected from CSRF.
Language Libraries
------------------
Bug Fixes
~~~~~~~~~
Python
""""""
* Fixed a bug in the extractor where a comment inside a subscript could sometimes cause the AST to be missing nodes.
* Using the :code:`break` and :code:`continue` keywords outside of a loop, which is a syntax error but is accepted by our parser, would cause the control-flow construction to fail. This is now no longer the case.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C#
""
* Full support for C# 13 / .NET 9. All new language features are now supported by the extractor. QL library and data flow support for the new C# 13 language constructs and generated MaD models for the .NET 9 runtime.
* C# 13: Add generated models for .NET 9.
* The models for :code:`System.Net.Http.HttpRequestMessage` and :code:`System.UriBuilder` have been modified to better model the flow of tainted URIs.
* Blazor :code:`[Parameter]` fields bound to a variable from the route specified in the :code:`@page` directive are now modeled as remote flow sources.
Golang
""""""
* Taint models have been added for the :code:`weak` package, which was added in Go 1.24.
* Taint models have been added for the interfaces :code:`TextAppender` and :code:`BinaryAppender` in the :code:`encoding` package, which were added in Go 1.24.
JavaScript/TypeScript
"""""""""""""""""""""
* Added support for regular expressions using the :code:`v` flag.
Deprecated APIs
~~~~~~~~~~~~~~~
C#
""
* The predicates :code:`immediatelyControls` and :code:`controls` on the :code:`ConditionBlock` class have been deprecated in favor of the newly added :code:`dominatingEdge` predicate.
Golang
""""""
* The class :code:`NamedType` has been deprecated. Use the new class :code:`DefinedType` instead. This better matches the terminology used in the Go language specification, which was changed in Go 1.9.
* The member predicate :code:`getNamedType` on :code:`GoMicro::ServiceInterfaceType` has been deprecated. Use the new member predicate :code:`getDefinedType` instead.
* The member predicate :code:`getNamedType` on :code:`Twirp::ServiceInterfaceType` has been deprecated. Use the new member predicate :code:`getDefinedType` instead.
Ruby
""""
* The predicates :code:`immediatelyControls` and :code:`controls` on the :code:`ConditionBlock` class have been deprecated in favor of the newly added :code:`dominatingEdge` predicate.
Swift
"""""
* The predicates :code:`immediatelyControls` and :code:`controls` on the :code:`ConditionBlock` class have been deprecated in favor of the newly added :code:`dominatingEdge` predicate.
New Features
~~~~~~~~~~~~
GitHub Actions
""""""""""""""
* The "Unpinned tag for a non-immutable Action in workflow" query (:code:`actions/unpinned-tag`) now supports expanding the trusted action owner list using data extensions (:code:`extensible: trustedActionsOwnerDataModel`). If you trust an Action publisher, you can include the owner name/organization in a model pack to add it to the allow list for this query. This addition will prevent security alerts when using unpinned tags for Actions published by that owner. For more information on creating a model pack, see `Creating a CodeQL Model Pack <https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack>`__.

View File

@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
.. toctree::
:maxdepth: 1
codeql-cli-2.20.5
codeql-cli-2.20.4
codeql-cli-2.20.3
codeql-cli-2.20.2

View File

@@ -66,7 +66,9 @@ write_file(
'DST_DIR="$(dirname "$(rlocation "$1")")"',
'mkdir -p "$DST_DIR/src/codegen/grammar"',
] + [
'cp -f --no-preserve=mode "$(rlocation "$%s")" "$DST_DIR/%s"' % item
# using cat instead of cp to honor default umask
# (also, macOS does not support `cp --no-preserve=mode`)
'cat "$(rlocation "$%s")" > "$DST_DIR/%s"' % item
for item in enumerate(_codegen_outs, 2)
],
is_executable = True,

View File

@@ -19,11 +19,17 @@ pub fn extractor_cli_config(_attr: TokenStream, item: TokenStream) -> TokenStrea
.fields
.iter()
.map(|f| {
let ty_tip = get_type_tip(&f.ty);
if f.ident.as_ref().is_some_and(|i| i != "inputs")
&& get_type_tip(&f.ty).is_some_and(|i| i == "Vec")
&& ty_tip.is_some_and(|i| i == "Vec")
{
quote! {
#[serde(deserialize_with="deserialize_newline_or_comma_separated")]
#[serde(deserialize_with="deserialize::deserialize_newline_or_comma_separated_vec")]
#f
}
} else if ty_tip.is_some_and(|i| i == "FxHashMap" || i == "HashMap") {
quote! {
#[serde(deserialize_with="deserialize::deserialize_newline_or_comma_separated_map")]
#f
}
} else {
@@ -60,7 +66,7 @@ pub fn extractor_cli_config(_attr: TokenStream, item: TokenStream) -> TokenStrea
quote! {
#f
}
} else if type_tip.is_some_and(|i| i == "Vec") {
} else if type_tip.is_some_and(|i| i == "Vec" || i == "FxHashMap" || i == "HashMap") {
quote! {
#[arg(long)]
#id: Option<String>

View File

@@ -1,9 +1,8 @@
mod deserialize_vec;
mod deserialize;
use anyhow::Context;
use clap::Parser;
use codeql_extractor::trap;
use deserialize_vec::deserialize_newline_or_comma_separated;
use figment::{
providers::{Env, Format, Serialized, Yaml},
value::Value,
@@ -13,14 +12,15 @@ use itertools::Itertools;
use ra_ap_cfg::{CfgAtom, CfgDiff};
use ra_ap_ide_db::FxHashMap;
use ra_ap_intern::Symbol;
use ra_ap_paths::{AbsPath, Utf8PathBuf};
use ra_ap_load_cargo::{LoadCargoConfig, ProcMacroServerChoice};
use ra_ap_paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
use ra_ap_project_model::{CargoConfig, CargoFeatures, CfgOverrides, RustLibSource, Sysroot};
use rust_extractor_macros::extractor_cli_config;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fmt::Debug;
use std::ops::Not;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, Clone, Copy, clap::ValueEnum)]
#[serde(rename_all = "lowercase")]
@@ -50,6 +50,9 @@ pub struct Config {
pub cargo_target: Option<String>,
pub cargo_features: Vec<String>,
pub cargo_cfg_overrides: Vec<String>,
pub cargo_extra_env: FxHashMap<String, String>,
pub cargo_extra_args: Vec<String>,
pub cargo_all_targets: bool,
pub logging_flamegraph: Option<PathBuf>,
pub logging_verbosity: Option<String>,
pub compression: Compression,
@@ -57,6 +60,12 @@ pub struct Config {
pub qltest: bool,
pub qltest_cargo_check: bool,
pub qltest_dependencies: Vec<String>,
pub sysroot: Option<PathBuf>,
pub sysroot_src: Option<PathBuf>,
pub rustc_src: Option<PathBuf>,
pub build_script_command: Vec<String>,
pub extra_includes: Vec<PathBuf>,
pub proc_macro_server: Option<PathBuf>,
}
impl Config {
@@ -92,45 +101,87 @@ impl Config {
figment.extract().context("loading configuration")
}
pub fn to_cargo_config(&self, dir: &AbsPath) -> CargoConfig {
let sysroot = Sysroot::discover(dir, &FxHashMap::default());
let sysroot_src = sysroot.src_root().map(ToOwned::to_owned);
let sysroot = sysroot
.root()
.map(ToOwned::to_owned)
.map(RustLibSource::Path);
let target_dir = self
.cargo_target_dir
.clone()
.unwrap_or_else(|| self.scratch_dir.join("target"));
let target_dir = Utf8PathBuf::from_path_buf(target_dir).ok();
let features = if self.cargo_features.is_empty() {
Default::default()
} else if self.cargo_features.contains(&"*".to_string()) {
CargoFeatures::All
} else {
CargoFeatures::Selected {
features: self.cargo_features.clone(),
no_default_features: false,
fn sysroot(&self, dir: &AbsPath) -> Sysroot {
let sysroot_input = self.sysroot.as_ref().map(|p| join_path_buf(dir, p));
let sysroot_src_input = self.sysroot_src.as_ref().map(|p| join_path_buf(dir, p));
match (sysroot_input, sysroot_src_input) {
(None, None) => Sysroot::discover(dir, &self.cargo_extra_env),
(Some(sysroot), None) => Sysroot::discover_sysroot_src_dir(sysroot),
(None, Some(sysroot_src)) => {
Sysroot::discover_with_src_override(dir, &self.cargo_extra_env, sysroot_src)
}
};
let target = self.cargo_target.clone();
let cfg_overrides = to_cfg_overrides(&self.cargo_cfg_overrides);
CargoConfig {
sysroot,
sysroot_src,
target_dir,
features,
target,
cfg_overrides,
..Default::default()
(Some(sysroot), Some(sysroot_src)) => Sysroot::new(Some(sysroot), Some(sysroot_src)),
}
}
fn proc_macro_server_choice(&self, dir: &AbsPath) -> ProcMacroServerChoice {
match &self.proc_macro_server {
Some(path) => match path.to_str() {
Some("none") => ProcMacroServerChoice::None,
Some("sysroot") => ProcMacroServerChoice::Sysroot,
_ => ProcMacroServerChoice::Explicit(join_path_buf(dir, path)),
},
None => ProcMacroServerChoice::Sysroot,
}
}
pub fn to_cargo_config(&self, dir: &AbsPath) -> (CargoConfig, LoadCargoConfig) {
let sysroot = self.sysroot(dir);
(
CargoConfig {
all_targets: self.cargo_all_targets,
sysroot_src: sysroot.src_root().map(ToOwned::to_owned),
rustc_source: self
.rustc_src
.as_ref()
.map(|p| join_path_buf(dir, p))
.or_else(|| sysroot.discover_rustc_src().map(AbsPathBuf::from))
.map(RustLibSource::Path),
sysroot: sysroot
.root()
.map(ToOwned::to_owned)
.map(RustLibSource::Path),
extra_env: self.cargo_extra_env.clone(),
extra_args: self.cargo_extra_args.clone(),
extra_includes: self
.extra_includes
.iter()
.map(|p| join_path_buf(dir, p))
.collect(),
target_dir: Utf8PathBuf::from_path_buf(
self.cargo_target_dir
.clone()
.unwrap_or_else(|| self.scratch_dir.join("target")),
)
.ok(),
features: if self.cargo_features.is_empty() {
Default::default()
} else if self.cargo_features.contains(&"*".to_string()) {
CargoFeatures::All
} else {
CargoFeatures::Selected {
features: self.cargo_features.clone(),
no_default_features: false,
}
},
target: self.cargo_target.clone(),
cfg_overrides: to_cfg_overrides(&self.cargo_cfg_overrides),
wrap_rustc_in_build_scripts: false,
run_build_script_command: if self.build_script_command.is_empty() {
None
} else {
Some(self.build_script_command.clone())
},
..Default::default()
},
LoadCargoConfig {
load_out_dirs_from_check: true,
with_proc_macro_server: self.proc_macro_server_choice(dir),
prefill_caches: false,
},
)
}
}
fn to_cfg_override(spec: &str) -> CfgAtom {
@@ -168,3 +219,10 @@ fn to_cfg_overrides(specs: &Vec<String>) -> CfgOverrides {
..Default::default()
}
}
fn join_path_buf(lhs: &AbsPath, rhs: &Path) -> AbsPathBuf {
let Ok(path) = Utf8PathBuf::from_path_buf(rhs.into()) else {
panic!("non utf8 input: {}", rhs.display())
};
lhs.join(path)
}

View File

@@ -0,0 +1,97 @@
use serde::de::{Error, Unexpected, Visitor};
use serde::Deserializer;
use std::collections::HashMap;
use std::fmt::Formatter;
use std::hash::BuildHasher;
use std::marker::PhantomData;
// phantom data is required to allow parametrizing on `T` without actual `T` data
struct VectorVisitor<T: From<String>>(PhantomData<T>);
struct MapVisitor<S: BuildHasher + Default>(PhantomData<S>);
impl<'de, T: From<String>> Visitor<'de> for VectorVisitor<T> {
type Value = Vec<T>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("either a sequence, or a comma or newline separated string")
}
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Vec<T>, E> {
Ok(value
.split(['\n', ','])
.map(|s| T::from(s.to_owned()))
.collect())
}
fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut ret = Vec::new();
while let Some(el) = seq.next_element::<String>()? {
ret.push(T::from(el));
}
Ok(ret)
}
}
impl<'de, S: BuildHasher + Default> Visitor<'de> for MapVisitor<S> {
type Value = HashMap<String, String, S>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str(
"either a sequence, or a comma or newline separated string of key=value entries",
)
}
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
value
.split(['\n', ','])
.map(|s| {
s.split_once('=')
.ok_or_else(|| E::custom(format!("key=value expected, found {s}")))
.map(|(key, value)| (key.to_owned(), value.to_owned()))
})
.collect()
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut ret = HashMap::with_hasher(Default::default());
while let Some(el) = seq.next_element::<String>()? {
let (key, value) = el
.split_once('=')
.ok_or_else(|| A::Error::invalid_value(Unexpected::Str(&el), &self))?;
ret.insert(key.to_owned(), value.to_owned());
}
Ok(ret)
}
}
/// deserialize into a vector of `T` either of:
/// * a sequence of elements serializable into `String`s, or
/// * a single element serializable into `String`, then split on `,` and `\n`
pub(crate) fn deserialize_newline_or_comma_separated_vec<
'a,
D: Deserializer<'a>,
T: From<String>,
>(
deserializer: D,
) -> Result<Vec<T>, D::Error> {
deserializer.deserialize_seq(VectorVisitor(PhantomData))
}
/// deserialize into a map of `String`s to `String`s either of:
/// * a sequence of elements serializable into `String`s, or
/// * a single element serializable into `String`, then split on `,` and `\n`
pub(crate) fn deserialize_newline_or_comma_separated_map<
'a,
D: Deserializer<'a>,
S: BuildHasher + Default,
>(
deserializer: D,
) -> Result<HashMap<String, String, S>, D::Error> {
deserializer.deserialize_map(MapVisitor(PhantomData))
}

View File

@@ -1,50 +0,0 @@
use serde::de::Visitor;
use serde::Deserializer;
use std::fmt::Formatter;
use std::marker::PhantomData;
// phantom data ise required to allow parametrizing on `T` without actual `T` data
struct VectorVisitor<T: From<String>>(PhantomData<T>);
impl<T: From<String>> VectorVisitor<T> {
fn new() -> Self {
VectorVisitor(PhantomData)
}
}
impl<'de, T: From<String>> Visitor<'de> for VectorVisitor<T> {
type Value = Vec<T>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("either a sequence, or a comma or newline separated string")
}
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Vec<T>, E> {
Ok(value
.split(['\n', ','])
.map(|s| T::from(s.to_owned()))
.collect())
}
fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut ret = Vec::new();
while let Some(el) = seq.next_element::<String>()? {
ret.push(T::from(el));
}
Ok(ret)
}
}
/// deserialize into a vector of `T` either of:
/// * a sequence of elements serializable into `String`s, or
/// * a single element serializable into `String`, then split on `,` and `\n`
///
/// This is required to be in scope when the `extractor_cli_config` macro is used.
pub(crate) fn deserialize_newline_or_comma_separated<'a, D: Deserializer<'a>, T: From<String>>(
deserializer: D,
) -> Result<Vec<T>, D::Error> {
deserializer.deserialize_seq(VectorVisitor::new())
}

View File

@@ -6,6 +6,7 @@ use archive::Archiver;
use ra_ap_hir::Semantics;
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_ide_db::RootDatabase;
use ra_ap_load_cargo::LoadCargoConfig;
use ra_ap_paths::{AbsPathBuf, Utf8PathBuf};
use ra_ap_project_model::{CargoConfig, ProjectManifest};
use ra_ap_vfs::Vfs;
@@ -114,9 +115,10 @@ impl<'a> Extractor<'a> {
&mut self,
project: &ProjectManifest,
config: &CargoConfig,
load_config: &LoadCargoConfig,
) -> Option<(RootDatabase, Vfs)> {
let before = Instant::now();
let ret = RustAnalyzer::load_workspace(project, config);
let ret = RustAnalyzer::load_workspace(project, config, load_config);
self.steps
.push(ExtractionStep::load_manifest(before, project));
ret
@@ -235,9 +237,12 @@ fn main() -> anyhow::Result<()> {
}
extractor.extract_without_semantics(file, "no manifest found");
}
let cargo_config = cfg.to_cargo_config(&cwd()?);
let cwd = cwd()?;
let (cargo_config, load_cargo_config) = cfg.to_cargo_config(&cwd);
for (manifest, files) in map.values().filter(|(_, files)| !files.is_empty()) {
if let Some((ref db, ref vfs)) = extractor.load_manifest(manifest, &cargo_config) {
if let Some((ref db, ref vfs)) =
extractor.load_manifest(manifest, &cargo_config, &load_cargo_config)
{
let semantics = Semantics::new(db);
for file in files {
match extractor.load_source(file, &semantics, vfs) {

View File

@@ -2,7 +2,7 @@ use itertools::Itertools;
use ra_ap_base_db::SourceDatabase;
use ra_ap_hir::Semantics;
use ra_ap_ide_db::RootDatabase;
use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
use ra_ap_load_cargo::{load_workspace_at, LoadCargoConfig};
use ra_ap_paths::{AbsPath, Utf8PathBuf};
use ra_ap_project_model::ProjectManifest;
use ra_ap_project_model::{CargoConfig, ManifestPath};
@@ -50,16 +50,12 @@ impl<'a> RustAnalyzer<'a> {
pub fn load_workspace(
project: &ProjectManifest,
config: &CargoConfig,
load_config: &LoadCargoConfig,
) -> Option<(RootDatabase, Vfs)> {
let progress = |t| (trace!("progress: {}", t));
let load_config = LoadCargoConfig {
load_out_dirs_from_check: true,
with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
let manifest = project.manifest_path();
match load_workspace_at(manifest.as_ref(), config, &load_config, &progress) {
match load_workspace_at(manifest.as_ref(), config, load_config, &progress) {
Ok((db, vfs, _macro_server)) => Some((db, vfs)),
Err(err) => {
error!("failed to load workspace for {}: {}", manifest, err);

View File

@@ -1,20 +1,38 @@
#!/bin/env python3
#!/usr/bin/env python3
import subprocess
import pathlib
import shutil
import sys
def tool(name):
ret = shutil.which(name)
assert ret, f"no {name} binary found on `PATH`"
return ret
this_dir = pathlib.Path(__file__).resolve().parent
cargo = shutil.which("cargo")
assert cargo, "no cargo binary found on `PATH`"
cargo = tool("cargo")
bazel = tool("bazel")
runs = []
runs.append(subprocess.run([cargo, "fmt", "--all", "--quiet"], cwd=this_dir))
def run(tool, args, *, cwd=this_dir):
print("+", tool, args)
runs.append(subprocess.run([tool] + args.split(), cwd=cwd))
# make sure bazel-provided sources are put in tree for `cargo` to work with them
run(bazel, "run ast-generator:inject-sources")
run(cargo, "fmt --all --quiet")
for manifest in this_dir.rglob("Cargo.toml"):
if not manifest.is_relative_to(this_dir / "ql") and not manifest.is_relative_to(this_dir / "integration-tests"):
runs.append(subprocess.run([cargo, "clippy", "--fix", "--allow-dirty", "--allow-staged", "--quiet", "--", "-D", "warnings"],
cwd=manifest.parent))
run(cargo,
"clippy --fix --allow-dirty --allow-staged --quiet -- -D warnings",
cwd=manifest.parent)
sys.exit(max(r.returncode for r in runs))

View File

@@ -132,8 +132,12 @@ abstract class ItemNode extends AstNode {
)
or
// a trait has access to the associated items of its supertraits
result = this.(TraitItemNode).resolveABound().getASuccessorRec(name) and
result instanceof AssocItemNode
this =
any(TraitItemNode trait |
result = trait.resolveABound().getASuccessorRec(name) and
result instanceof AssocItemNode and
not trait.hasAssocItem(name)
)
or
// items made available by an implementation where `this` is the implementing type
exists(ItemNode node |
@@ -141,6 +145,18 @@ abstract class ItemNode extends AstNode {
result = node.getASuccessorRec(name) and
result instanceof AssocItemNode
)
or
// trait items with default implementations made available in an implementation
exists(ImplItemNode impl, ItemNode trait |
this = impl and
trait = impl.resolveTraitTy() and
result = trait.getASuccessorRec(name) and
result.(AssocItemNode).hasImplementation() and
not impl.hasAssocItem(name)
)
or
// type parameters have access to the associated items of its bounds
result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
}
/** Gets a successor named `name` of this item, if any. */
@@ -163,6 +179,9 @@ abstract class ItemNode extends AstNode {
name = "crate" and
result.(SourceFileItemNode).getFile() = this.getFile()
}
/** Gets the location of this item. */
Location getLocation() { result = super.getLocation() }
}
/** A module or a source file. */
@@ -191,11 +210,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
}
/** An item that can occur in a trait or an `impl` block. */
abstract private class AssocItemNode extends ItemNode { }
abstract private class AssocItemNode extends ItemNode, AssocItem {
/** Holds if this associated item has an implementation. */
abstract predicate hasImplementation();
}
private class ConstItemNode extends AssocItemNode instanceof Const {
override string getName() { result = Const.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override Namespace getNamespace() { result.isValue() }
override Visibility getVisibility() { result = Const.super.getVisibility() }
@@ -219,9 +243,11 @@ private class VariantItemNode extends ItemNode instanceof Variant {
override Visibility getVisibility() { result = Variant.super.getVisibility() }
}
private class FunctionItemNode extends AssocItemNode instanceof Function {
class FunctionItemNode extends AssocItemNode instanceof Function {
override string getName() { result = Function.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override Namespace getNamespace() { result.isValue() }
override Visibility getVisibility() { result = Function.super.getVisibility() }
@@ -242,7 +268,19 @@ abstract private class ImplOrTraitItemNode extends ItemNode {
}
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
ItemNode resolveSelfTy() { result = resolvePath(super.getSelfTy().(PathTypeRepr).getPath()) }
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
ItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
/** Holds if this `impl` block declares an associated item named `name`. */
pragma[nomagic]
predicate hasAssocItem(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
}
override string getName() { result = "(impl)" }
@@ -256,6 +294,8 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
override string getName() { result = "(macro call)" }
override predicate hasImplementation() { none() }
override Namespace getNamespace() { none() }
override Visibility getVisibility() { none() }
@@ -290,6 +330,12 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
/** Holds if this trait declares an associated item named `name`. */
pragma[nomagic]
predicate hasAssocItem(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
}
override string getName() { result = Trait.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
@@ -300,6 +346,8 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
override string getName() { result = TypeAlias.super.getName().getText() }
override predicate hasImplementation() { super.hasTypeRepr() }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = TypeAlias.super.getVisibility() }
@@ -330,11 +378,20 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
}
private class TypeParamItemNode extends ItemNode instanceof TypeParam {
pragma[nomagic]
Path getABoundPath() {
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
}
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
override string getName() { result = TypeParam.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { none() }
override Location getLocation() { result = TypeParam.super.getName().getLocation() }
}
/** Holds if `item` has the name `name` and is a top-level item inside `f`. */

View File

@@ -357,6 +357,11 @@ mod m16 {
fn g(&self) -> T // $ item=I84
; // I85
fn h(&self) -> T { // $ item=I84
Self::g(&self); // $ item=I85
self.g() // $ MISSING: item=I85
} // I96
const c: T // $ item=I84
; // I94
} // I86
@@ -425,6 +430,8 @@ mod m16 {
>::f(&x); // $ MISSING: item=I93
S::g(&x); // $ item=I92
x.g(); // $ MISSING: item=I92
S::h(&x); // $ item=I96
x.h(); // $ MISSING: item=I96
S::c; // $ item=I95
<S // $ item=I90
as Trait1<
@@ -434,6 +441,38 @@ mod m16 {
} // I83
}
mod m17 {
trait MyTrait {
fn f(&self); // I1
} // I2
struct S; // I3
#[rustfmt::skip]
impl MyTrait // $ item=I2
for S { // $ item=I3
fn f(&self) {
println!("M17::MyTrait::f");
} // I4
}
#[rustfmt::skip]
fn g<T: // I5
MyTrait // $ item=I2
>(x: T) { // $ item=I5
x.f(); // $ MISSING: item=I1
T::f(&x); // $ item=I1
MyTrait::f(&x); // $ item=I1
} // I6
#[rustfmt::skip]
pub fn f() {
g( // $ item=I6
S // $ item=I3
);
} // I99
}
fn main() {
my::nested::nested1::nested2::f(); // $ item=I4
my::f(); // $ item=I38
@@ -455,4 +494,5 @@ fn main() {
m11::f(); // $ item=I63
m15::f(); // $ item=I75
m16::f(); // $ item=I83
m17::f(); // $ item=I99
}

View File

@@ -2,9 +2,9 @@ testFailures
| main.rs:183:10:183:16 | MyTrait | Fixed missing result: item=I47 |
| main.rs:340:14:340:19 | Trait1 | Fixed missing result: item=I79 |
| main.rs:343:14:343:19 | Trait2 | Unexpected result: item=I82 |
| main.rs:417:14:419:11 | Trait1::<...> | Fixed missing result: item=I86 |
| main.rs:422:14:424:11 | Trait2::<...> | Unexpected result: item=I89 |
| main.rs:430:14:432:11 | Trait1::<...> | Fixed missing result: item=I86 |
| main.rs:422:14:424:11 | Trait1::<...> | Fixed missing result: item=I86 |
| main.rs:427:14:429:11 | Trait2::<...> | Unexpected result: item=I89 |
| main.rs:437:14:439:11 | Trait1::<...> | Fixed missing result: item=I86 |
mod
| lib.rs:1:1:1:7 | mod my |
| main.rs:1:1:1:7 | mod my |
@@ -25,7 +25,8 @@ mod
| main.rs:279:1:292:1 | mod m13 |
| main.rs:283:5:291:5 | mod m14 |
| main.rs:294:1:348:1 | mod m15 |
| main.rs:350:1:435:1 | mod m16 |
| main.rs:350:1:442:1 | mod m16 |
| main.rs:444:1:474:1 | mod m17 |
| my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/nested2.rs:1:1:11:1 | mod nested3 |
| my2/nested2.rs:2:5:10:5 | mod nested4 |
@@ -51,7 +52,7 @@ resolvePath
| main.rs:30:17:30:21 | super | main.rs:18:5:36:5 | mod m2 |
| main.rs:30:17:30:24 | ...::f | main.rs:19:9:21:9 | fn f |
| main.rs:33:17:33:17 | f | main.rs:19:9:21:9 | fn f |
| main.rs:40:9:40:13 | super | main.rs:1:1:458:2 | SourceFile |
| main.rs:40:9:40:13 | super | main.rs:1:1:498:2 | SourceFile |
| main.rs:40:9:40:17 | ...::m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:40:9:40:21 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:40:9:40:24 | ...::g | main.rs:23:9:27:9 | fn g |
@@ -63,7 +64,7 @@ resolvePath
| main.rs:61:17:61:19 | Foo | main.rs:59:9:59:21 | struct Foo |
| main.rs:64:13:64:15 | Foo | main.rs:53:5:53:17 | struct Foo |
| main.rs:66:5:66:5 | f | main.rs:55:5:62:5 | fn f |
| main.rs:68:5:68:8 | self | main.rs:1:1:458:2 | SourceFile |
| main.rs:68:5:68:8 | self | main.rs:1:1:498:2 | SourceFile |
| main.rs:68:5:68:11 | ...::i | main.rs:71:1:83:1 | fn i |
| main.rs:74:13:74:15 | Foo | main.rs:48:1:48:13 | struct Foo |
| main.rs:81:17:81:19 | Foo | main.rs:77:9:79:9 | struct Foo |
@@ -77,7 +78,7 @@ resolvePath
| main.rs:87:57:87:66 | ...::g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:87:80:87:86 | nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:100:5:100:22 | f_defined_in_macro | main.rs:99:18:99:42 | fn f_defined_in_macro |
| main.rs:117:13:117:17 | super | main.rs:1:1:458:2 | SourceFile |
| main.rs:117:13:117:17 | super | main.rs:1:1:498:2 | SourceFile |
| main.rs:117:13:117:21 | ...::m5 | main.rs:103:1:107:1 | mod m5 |
| main.rs:118:9:118:9 | f | main.rs:104:5:106:5 | fn f |
| main.rs:118:9:118:9 | f | main.rs:110:5:112:5 | fn f |
@@ -132,7 +133,7 @@ resolvePath
| main.rs:274:16:274:16 | T | main.rs:268:7:268:7 | T |
| main.rs:275:14:275:17 | Self | main.rs:266:5:276:5 | trait MyParamTrait |
| main.rs:275:14:275:33 | ...::AssociatedType | main.rs:270:9:270:28 | TypeAlias |
| main.rs:284:13:284:17 | crate | main.rs:1:1:458:2 | SourceFile |
| main.rs:284:13:284:17 | crate | main.rs:1:1:498:2 | SourceFile |
| main.rs:284:13:284:22 | ...::m13 | main.rs:279:1:292:1 | mod m13 |
| main.rs:284:13:284:25 | ...::f | main.rs:280:5:280:17 | fn f |
| main.rs:284:13:284:25 | ...::f | main.rs:280:19:281:19 | struct f |
@@ -157,86 +158,103 @@ resolvePath
| main.rs:345:9:345:12 | ...::g | main.rs:322:9:324:9 | fn g |
| main.rs:355:24:355:24 | T | main.rs:353:7:353:7 | T |
| main.rs:357:24:357:24 | T | main.rs:353:7:353:7 | T |
| main.rs:360:18:360:18 | T | main.rs:353:7:353:7 | T |
| main.rs:368:9:370:9 | Trait1::<...> | main.rs:351:5:362:5 | trait Trait1 |
| main.rs:369:11:369:11 | T | main.rs:366:7:366:7 | T |
| main.rs:371:24:371:24 | T | main.rs:366:7:366:7 | T |
| main.rs:373:13:373:16 | Self | main.rs:364:5:377:5 | trait Trait2 |
| main.rs:373:13:373:19 | ...::g | main.rs:357:9:358:9 | fn g |
| main.rs:375:13:375:16 | Self | main.rs:364:5:377:5 | trait Trait2 |
| main.rs:375:13:375:19 | ...::c | main.rs:360:9:361:9 | Const |
| main.rs:382:10:384:5 | Trait1::<...> | main.rs:351:5:362:5 | trait Trait1 |
| main.rs:383:7:383:7 | S | main.rs:379:5:379:13 | struct S |
| main.rs:385:11:385:11 | S | main.rs:379:5:379:13 | struct S |
| main.rs:386:24:386:24 | S | main.rs:379:5:379:13 | struct S |
| main.rs:388:13:388:16 | Self | main.rs:381:5:399:5 | impl Trait1::<...> for S { ... } |
| main.rs:388:13:388:19 | ...::g | main.rs:392:9:395:9 | fn g |
| main.rs:392:24:392:24 | S | main.rs:379:5:379:13 | struct S |
| main.rs:394:13:394:16 | Self | main.rs:381:5:399:5 | impl Trait1::<...> for S { ... } |
| main.rs:394:13:394:19 | ...::c | main.rs:397:9:398:9 | Const |
| main.rs:397:18:397:18 | S | main.rs:379:5:379:13 | struct S |
| main.rs:397:22:397:22 | S | main.rs:379:5:379:13 | struct S |
| main.rs:402:10:404:5 | Trait2::<...> | main.rs:364:5:377:5 | trait Trait2 |
| main.rs:403:7:403:7 | S | main.rs:379:5:379:13 | struct S |
| main.rs:405:11:405:11 | S | main.rs:379:5:379:13 | struct S |
| main.rs:406:24:406:24 | S | main.rs:379:5:379:13 | struct S |
| main.rs:408:13:408:16 | Self | main.rs:401:5:410:5 | impl Trait2::<...> for S { ... } |
| main.rs:415:17:415:17 | S | main.rs:379:5:379:13 | struct S |
| main.rs:416:10:416:10 | S | main.rs:379:5:379:13 | struct S |
| main.rs:417:14:419:11 | Trait1::<...> | main.rs:351:5:362:5 | trait Trait1 |
| main.rs:418:13:418:13 | S | main.rs:379:5:379:13 | struct S |
| main.rs:421:10:421:10 | S | main.rs:379:5:379:13 | struct S |
| main.rs:422:14:424:11 | Trait2::<...> | main.rs:364:5:377:5 | trait Trait2 |
| main.rs:423:13:423:13 | S | main.rs:379:5:379:13 | struct S |
| main.rs:426:9:426:9 | S | main.rs:379:5:379:13 | struct S |
| main.rs:426:9:426:12 | ...::g | main.rs:392:9:395:9 | fn g |
| main.rs:428:9:428:9 | S | main.rs:379:5:379:13 | struct S |
| main.rs:428:9:428:12 | ...::c | main.rs:397:9:398:9 | Const |
| main.rs:429:10:429:10 | S | main.rs:379:5:379:13 | struct S |
| main.rs:430:14:432:11 | Trait1::<...> | main.rs:351:5:362:5 | trait Trait1 |
| main.rs:431:13:431:13 | S | main.rs:379:5:379:13 | struct S |
| main.rs:438:5:438:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:438:5:438:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:438:5:438:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:438:5:438:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:438:5:438:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:439:5:439:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:439:5:439:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:440:5:440:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:440:5:440:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:440:5:440:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:440:5:440:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:441:5:441:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:442:5:442:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:443:5:443:9 | crate | main.rs:1:1:458:2 | SourceFile |
| main.rs:443:5:443:12 | ...::h | main.rs:50:1:69:1 | fn h |
| main.rs:444:5:444:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:444:5:444:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:444:5:444:13 | ...::g | main.rs:23:9:27:9 | fn g |
| main.rs:445:5:445:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:445:5:445:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:445:5:445:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
| main.rs:445:5:445:17 | ...::h | main.rs:30:27:34:13 | fn h |
| main.rs:446:5:446:6 | m4 | main.rs:39:1:46:1 | mod m4 |
| main.rs:446:5:446:9 | ...::i | main.rs:42:5:45:5 | fn i |
| main.rs:447:5:447:5 | h | main.rs:50:1:69:1 | fn h |
| main.rs:448:5:448:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:449:5:449:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:450:5:450:5 | j | main.rs:97:1:101:1 | fn j |
| main.rs:451:5:451:6 | m6 | main.rs:109:1:120:1 | mod m6 |
| main.rs:451:5:451:9 | ...::g | main.rs:114:5:119:5 | fn g |
| main.rs:452:5:452:6 | m7 | main.rs:122:1:137:1 | mod m7 |
| main.rs:452:5:452:9 | ...::f | main.rs:129:5:136:5 | fn f |
| main.rs:453:5:453:6 | m8 | main.rs:139:1:193:1 | mod m8 |
| main.rs:453:5:453:9 | ...::g | main.rs:177:5:192:5 | fn g |
| main.rs:454:5:454:6 | m9 | main.rs:195:1:203:1 | mod m9 |
| main.rs:454:5:454:9 | ...::f | main.rs:198:5:202:5 | fn f |
| main.rs:455:5:455:7 | m11 | main.rs:226:1:263:1 | mod m11 |
| main.rs:455:5:455:10 | ...::f | main.rs:231:5:234:5 | fn f |
| main.rs:456:5:456:7 | m15 | main.rs:294:1:348:1 | mod m15 |
| main.rs:456:5:456:10 | ...::f | main.rs:335:5:347:5 | fn f |
| main.rs:457:5:457:7 | m16 | main.rs:350:1:435:1 | mod m16 |
| main.rs:457:5:457:10 | ...::f | main.rs:412:5:434:5 | fn f |
| main.rs:360:24:360:24 | T | main.rs:353:7:353:7 | T |
| main.rs:361:13:361:16 | Self | main.rs:351:5:367:5 | trait Trait1 |
| main.rs:361:13:361:19 | ...::g | main.rs:357:9:358:9 | fn g |
| main.rs:365:18:365:18 | T | main.rs:353:7:353:7 | T |
| main.rs:373:9:375:9 | Trait1::<...> | main.rs:351:5:367:5 | trait Trait1 |
| main.rs:374:11:374:11 | T | main.rs:371:7:371:7 | T |
| main.rs:376:24:376:24 | T | main.rs:371:7:371:7 | T |
| main.rs:378:13:378:16 | Self | main.rs:369:5:382:5 | trait Trait2 |
| main.rs:378:13:378:19 | ...::g | main.rs:357:9:358:9 | fn g |
| main.rs:380:13:380:16 | Self | main.rs:369:5:382:5 | trait Trait2 |
| main.rs:380:13:380:19 | ...::c | main.rs:365:9:366:9 | Const |
| main.rs:387:10:389:5 | Trait1::<...> | main.rs:351:5:367:5 | trait Trait1 |
| main.rs:388:7:388:7 | S | main.rs:384:5:384:13 | struct S |
| main.rs:390:11:390:11 | S | main.rs:384:5:384:13 | struct S |
| main.rs:391:24:391:24 | S | main.rs:384:5:384:13 | struct S |
| main.rs:393:13:393:16 | Self | main.rs:386:5:404:5 | impl Trait1::<...> for S { ... } |
| main.rs:393:13:393:19 | ...::g | main.rs:397:9:400:9 | fn g |
| main.rs:397:24:397:24 | S | main.rs:384:5:384:13 | struct S |
| main.rs:399:13:399:16 | Self | main.rs:386:5:404:5 | impl Trait1::<...> for S { ... } |
| main.rs:399:13:399:19 | ...::c | main.rs:402:9:403:9 | Const |
| main.rs:402:18:402:18 | S | main.rs:384:5:384:13 | struct S |
| main.rs:402:22:402:22 | S | main.rs:384:5:384:13 | struct S |
| main.rs:407:10:409:5 | Trait2::<...> | main.rs:369:5:382:5 | trait Trait2 |
| main.rs:408:7:408:7 | S | main.rs:384:5:384:13 | struct S |
| main.rs:410:11:410:11 | S | main.rs:384:5:384:13 | struct S |
| main.rs:411:24:411:24 | S | main.rs:384:5:384:13 | struct S |
| main.rs:413:13:413:16 | Self | main.rs:406:5:415:5 | impl Trait2::<...> for S { ... } |
| main.rs:420:17:420:17 | S | main.rs:384:5:384:13 | struct S |
| main.rs:421:10:421:10 | S | main.rs:384:5:384:13 | struct S |
| main.rs:422:14:424:11 | Trait1::<...> | main.rs:351:5:367:5 | trait Trait1 |
| main.rs:423:13:423:13 | S | main.rs:384:5:384:13 | struct S |
| main.rs:426:10:426:10 | S | main.rs:384:5:384:13 | struct S |
| main.rs:427:14:429:11 | Trait2::<...> | main.rs:369:5:382:5 | trait Trait2 |
| main.rs:428:13:428:13 | S | main.rs:384:5:384:13 | struct S |
| main.rs:431:9:431:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:431:9:431:12 | ...::g | main.rs:397:9:400:9 | fn g |
| main.rs:433:9:433:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:433:9:433:12 | ...::h | main.rs:360:9:363:9 | fn h |
| main.rs:435:9:435:9 | S | main.rs:384:5:384:13 | struct S |
| main.rs:435:9:435:12 | ...::c | main.rs:402:9:403:9 | Const |
| main.rs:436:10:436:10 | S | main.rs:384:5:384:13 | struct S |
| main.rs:437:14:439:11 | Trait1::<...> | main.rs:351:5:367:5 | trait Trait1 |
| main.rs:438:13:438:13 | S | main.rs:384:5:384:13 | struct S |
| main.rs:452:10:452:16 | MyTrait | main.rs:445:5:447:5 | trait MyTrait |
| main.rs:453:9:453:9 | S | main.rs:449:5:449:13 | struct S |
| main.rs:461:7:461:13 | MyTrait | main.rs:445:5:447:5 | trait MyTrait |
| main.rs:462:10:462:10 | T | main.rs:460:10:460:10 | T |
| main.rs:464:9:464:9 | T | main.rs:460:10:460:10 | T |
| main.rs:464:9:464:12 | ...::f | main.rs:446:9:446:20 | fn f |
| main.rs:465:9:465:15 | MyTrait | main.rs:445:5:447:5 | trait MyTrait |
| main.rs:465:9:465:18 | ...::f | main.rs:446:9:446:20 | fn f |
| main.rs:470:9:470:9 | g | main.rs:459:5:466:5 | fn g |
| main.rs:471:11:471:11 | S | main.rs:449:5:449:13 | struct S |
| main.rs:477:5:477:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:477:5:477:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:477:5:477:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:477:5:477:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:477:5:477:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:478:5:478:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:478:5:478:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:479:5:479:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:479:5:479:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:479:5:479:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:479:5:479:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:480:5:480:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:481:5:481:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:482:5:482:9 | crate | main.rs:1:1:498:2 | SourceFile |
| main.rs:482:5:482:12 | ...::h | main.rs:50:1:69:1 | fn h |
| main.rs:483:5:483:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:483:5:483:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:483:5:483:13 | ...::g | main.rs:23:9:27:9 | fn g |
| main.rs:484:5:484:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:484:5:484:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:484:5:484:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
| main.rs:484:5:484:17 | ...::h | main.rs:30:27:34:13 | fn h |
| main.rs:485:5:485:6 | m4 | main.rs:39:1:46:1 | mod m4 |
| main.rs:485:5:485:9 | ...::i | main.rs:42:5:45:5 | fn i |
| main.rs:486:5:486:5 | h | main.rs:50:1:69:1 | fn h |
| main.rs:487:5:487:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:488:5:488:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:489:5:489:5 | j | main.rs:97:1:101:1 | fn j |
| main.rs:490:5:490:6 | m6 | main.rs:109:1:120:1 | mod m6 |
| main.rs:490:5:490:9 | ...::g | main.rs:114:5:119:5 | fn g |
| main.rs:491:5:491:6 | m7 | main.rs:122:1:137:1 | mod m7 |
| main.rs:491:5:491:9 | ...::f | main.rs:129:5:136:5 | fn f |
| main.rs:492:5:492:6 | m8 | main.rs:139:1:193:1 | mod m8 |
| main.rs:492:5:492:9 | ...::g | main.rs:177:5:192:5 | fn g |
| main.rs:493:5:493:6 | m9 | main.rs:195:1:203:1 | mod m9 |
| main.rs:493:5:493:9 | ...::f | main.rs:198:5:202:5 | fn f |
| main.rs:494:5:494:7 | m11 | main.rs:226:1:263:1 | mod m11 |
| main.rs:494:5:494:10 | ...::f | main.rs:231:5:234:5 | fn f |
| main.rs:495:5:495:7 | m15 | main.rs:294:1:348:1 | mod m15 |
| main.rs:495:5:495:10 | ...::f | main.rs:335:5:347:5 | fn f |
| main.rs:496:5:496:7 | m16 | main.rs:350:1:442:1 | mod m16 |
| main.rs:496:5:496:10 | ...::f | main.rs:417:5:441:5 | fn f |
| main.rs:497:5:497:7 | m17 | main.rs:444:1:474:1 | mod m17 |
| main.rs:497:5:497:10 | ...::f | main.rs:468:5:473:5 | fn f |
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| my2/mod.rs:5:5:5:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |