Skip to content

Commit e13bb0f

Browse files
authored
Merge pull request #20879 from paldepind/rust/reads-as-taint
Rust: Lift content reads as taint steps
2 parents 6feded9 + 74a77a7 commit e13bb0f

File tree

16 files changed

+279
-150
lines changed

16 files changed

+279
-150
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Reading content of a value now carries taint if the value itself is tainted. For instance, if `s` is tainted then `s.field` is also tainted. This generally improves taint flow.

rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ private import codeql.rust.dataflow.FlowSummary
1111
private import codeql.rust.dataflow.Ssa
1212
private import Content
1313

14+
predicate encodeContentTupleField(TupleFieldContent c, string arg) {
15+
exists(Addressable a, int pos, string prefix |
16+
arg = prefix + "(" + pos + ")" and prefix = a.getCanonicalPath()
17+
|
18+
c.isStructField(a, pos) or c.isVariantField(a, pos)
19+
)
20+
}
21+
22+
predicate encodeContentStructField(StructFieldContent c, string arg) {
23+
exists(Addressable a, string field | arg = a.getCanonicalPath() + "::" + field |
24+
c.isStructField(a, field) or c.isVariantField(a, field)
25+
)
26+
}
27+
1428
module Input implements InputSig<Location, RustDataFlow> {
1529
private import codeql.rust.frameworks.stdlib.Stdlib
1630

@@ -58,24 +72,11 @@ module Input implements InputSig<Location, RustDataFlow> {
5872
exists(Content c | cs = TSingletonContentSet(c) |
5973
result = "Field" and
6074
(
61-
exists(Addressable a, int pos, string prefix |
62-
arg = prefix + "(" + pos + ")" and prefix = a.getCanonicalPath()
63-
|
64-
c.(TupleFieldContent).isStructField(a, pos)
65-
or
66-
c.(TupleFieldContent).isVariantField(a, pos)
67-
)
75+
encodeContentTupleField(c, arg)
6876
or
69-
exists(Addressable a, string field | arg = a.getCanonicalPath() + "::" + field |
70-
c.(StructFieldContent).isStructField(a, field)
71-
or
72-
c.(StructFieldContent).isVariantField(a, field)
73-
)
77+
encodeContentStructField(c, arg)
7478
or
75-
exists(int pos |
76-
c = TTuplePositionContent(pos) and
77-
arg = pos.toString()
78-
)
79+
exists(int pos | c = TTuplePositionContent(pos) and arg = pos.toString())
7980
)
8081
or
8182
result = "Reference" and

rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ private import Node as Node
77
private import Content
88
private import FlowSummaryImpl as FlowSummaryImpl
99
private import codeql.rust.internal.CachedStages
10+
private import codeql.rust.internal.TypeInference as TypeInference
11+
private import codeql.rust.internal.Type as Type
12+
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
13+
14+
/**
15+
* Holds if the field `field` should, by default, be excluded from taint steps
16+
* from the containing type to reads of the field. The models-as-data syntax
17+
* used to denote the field is the same as for `Field[]` access path elements.
18+
*/
19+
extensible predicate excludeFieldTaintStep(string field);
20+
21+
/**
22+
* Holds if the content `c` corresponds to a field that has explicitly been
23+
* excluded as a taint step.
24+
*/
25+
private predicate excludedTaintStepContent(Content c) {
26+
exists(string arg | excludeFieldTaintStep(arg) |
27+
FlowSummaryImpl::encodeContentStructField(c, arg) or
28+
FlowSummaryImpl::encodeContentTupleField(c, arg)
29+
)
30+
}
1031

1132
module RustTaintTracking implements InputSig<Location, RustDataFlow> {
1233
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
@@ -28,11 +49,17 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
2849
succ.asExpr() = index
2950
)
3051
or
31-
// Although data flow through collections and references is modeled using
32-
// stores/reads, we also allow taint to flow out of a tainted collection
33-
// or reference.
34-
// This is needed in order to support taint-tracking configurations where
35-
// the source is a collection or reference.
52+
// Read steps give rise to taint steps. This has the effect that if `foo`
53+
// is tainted and an operation reads from `foo` (e.g., `foo.bar`) then
54+
// taint is propagated.
55+
exists(Content c |
56+
RustDataFlow::readContentStep(pred, c, succ) and
57+
not excludedTaintStepContent(c)
58+
)
59+
or
60+
// In addition to the above, for element and reference content we let
61+
// _all_ read steps (including those from flow summaries and those that
62+
// result in small primitive types) give rise to taint steps.
3663
exists(SingletonContentSet cs | RustDataFlow::readStep(pred, cs, succ) |
3764
cs.getContent() instanceof ElementContent
3865
or

rust/ql/lib/codeql/rust/frameworks/actix-web.model.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,4 @@ extensions:
1515
pack: codeql/rust-all
1616
extensible: summaryModel
1717
data:
18-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue", "taint", "manual"]
19-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue.Field[0]", "taint", "manual"]
20-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue.Field[1]", "taint", "manual"]
21-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue.Field[2]", "taint", "manual"]
22-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue.Field[3]", "taint", "manual"]
23-
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue.Field[4]", "taint", "manual"]
18+
- ["<actix_web::types::path::Path>::into_inner", "Argument[self]", "ReturnValue", "taint", "manual"]

rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,9 @@ extensions:
141141
- ["core::ptr::write_bytes", "Argument[0]", "pointer-access", "manual"]
142142
- ["core::ptr::write_unaligned", "Argument[0]", "pointer-access", "manual"]
143143
- ["core::ptr::write_volatile", "Argument[0]", "pointer-access", "manual"]
144+
- addsTo:
145+
pack: codeql/rust-all
146+
extensible: excludeFieldTaintStep
147+
data:
148+
- ["core::ops::range::RangeInclusive::start"]
149+
- ["core::ops::range::RangeInclusive::end"]

rust/ql/test/library-tests/dataflow/global/inline-flow.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,13 @@ edges
185185
| main.rs:306:30:306:56 | ...::take_second(...) [MyInt] | main.rs:306:9:306:26 | MyInt {...} [MyInt] | provenance | |
186186
| main.rs:306:55:306:55 | b [MyInt] | main.rs:293:26:293:37 | ...: MyInt [MyInt] | provenance | |
187187
| main.rs:306:55:306:55 | b [MyInt] | main.rs:306:30:306:56 | ...::take_second(...) [MyInt] | provenance | |
188+
| main.rs:315:32:319:1 | { ... } | main.rs:322:13:322:26 | async_source(...) | provenance | |
188189
| main.rs:315:32:319:1 | { ... } | main.rs:334:41:334:54 | async_source(...) | provenance | |
189190
| main.rs:316:9:316:9 | a | main.rs:315:32:319:1 | { ... } | provenance | |
190191
| main.rs:316:9:316:9 | a | main.rs:317:10:317:10 | a | provenance | |
191192
| main.rs:316:13:316:21 | source(...) | main.rs:316:9:316:9 | a | provenance | |
193+
| main.rs:322:9:322:9 | a | main.rs:323:10:323:10 | a | provenance | |
194+
| main.rs:322:13:322:26 | async_source(...) | main.rs:322:9:322:9 | a | provenance | |
192195
| main.rs:326:13:326:13 | c | main.rs:327:14:327:14 | c | provenance | |
193196
| main.rs:326:17:326:25 | source(...) | main.rs:326:13:326:13 | c | provenance | |
194197
| main.rs:334:9:334:9 | a | main.rs:335:10:335:10 | a | provenance | |
@@ -419,6 +422,9 @@ nodes
419422
| main.rs:316:9:316:9 | a | semmle.label | a |
420423
| main.rs:316:13:316:21 | source(...) | semmle.label | source(...) |
421424
| main.rs:317:10:317:10 | a | semmle.label | a |
425+
| main.rs:322:9:322:9 | a | semmle.label | a |
426+
| main.rs:322:13:322:26 | async_source(...) | semmle.label | async_source(...) |
427+
| main.rs:323:10:323:10 | a | semmle.label | a |
422428
| main.rs:326:13:326:13 | c | semmle.label | c |
423429
| main.rs:326:17:326:25 | source(...) | semmle.label | source(...) |
424430
| main.rs:327:14:327:14 | c | semmle.label | c |
@@ -503,6 +509,7 @@ testFailures
503509
| main.rs:302:10:302:10 | c | main.rs:299:28:299:36 | source(...) | main.rs:302:10:302:10 | c | $@ | main.rs:299:28:299:36 | source(...) | source(...) |
504510
| main.rs:307:10:307:10 | c | main.rs:305:28:305:37 | source(...) | main.rs:307:10:307:10 | c | $@ | main.rs:305:28:305:37 | source(...) | source(...) |
505511
| main.rs:317:10:317:10 | a | main.rs:316:13:316:21 | source(...) | main.rs:317:10:317:10 | a | $@ | main.rs:316:13:316:21 | source(...) | source(...) |
512+
| main.rs:323:10:323:10 | a | main.rs:316:13:316:21 | source(...) | main.rs:323:10:323:10 | a | $@ | main.rs:316:13:316:21 | source(...) | source(...) |
506513
| main.rs:327:14:327:14 | c | main.rs:326:17:326:25 | source(...) | main.rs:327:14:327:14 | c | $@ | main.rs:326:17:326:25 | source(...) | source(...) |
507514
| main.rs:335:10:335:10 | a | main.rs:316:13:316:21 | source(...) | main.rs:335:10:335:10 | a | $@ | main.rs:316:13:316:21 | source(...) | source(...) |
508515
| main.rs:384:14:384:15 | n1 | main.rs:359:13:359:21 | source(...) | main.rs:384:14:384:15 | n1 | $@ | main.rs:359:13:359:21 | source(...) | source(...) |

rust/ql/test/library-tests/dataflow/global/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ async fn async_source() -> i64 {
320320

321321
async fn test_async_await_async_part() {
322322
let a = async_source().await;
323-
sink(a); // $ MISSING: hasValueFlow=1
323+
sink(a); // $ hasTaintFlow=1 MISSING: hasValueFlow=1
324324

325325
let b = async {
326326
let c = source(2);

rust/ql/test/library-tests/dataflow/sources/database/InlineFlow.expected

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ edges
5050
| test.rs:42:20:42:21 | t1 [element] | test.rs:42:13:42:15 | row | provenance | |
5151
| test.rs:48:22:48:30 | query_map | test.rs:50:14:50:24 | ...: i64 | provenance | Src:MaD:3 |
5252
| test.rs:50:14:50:24 | ...: i64 | test.rs:51:22:51:27 | values | provenance | |
53+
| test.rs:55:22:55:30 | query_map | test.rs:57:14:57:39 | ...: ... | provenance | Src:MaD:3 |
54+
| test.rs:57:14:57:39 | ...: ... | test.rs:58:22:58:29 | values.0 | provenance | |
55+
| test.rs:57:14:57:39 | ...: ... | test.rs:59:22:59:29 | values.1 | provenance | |
56+
| test.rs:57:14:57:39 | ...: ... | test.rs:60:22:60:29 | values.2 | provenance | |
5357
| test.rs:64:13:64:17 | total | test.rs:68:14:68:18 | total | provenance | |
5458
| test.rs:64:21:67:10 | conn.query_fold(...) [Ok] | test.rs:64:21:67:11 | TryExpr | provenance | |
5559
| test.rs:64:21:67:11 | TryExpr | test.rs:64:13:64:17 | total | provenance | |
@@ -61,6 +65,13 @@ edges
6165
| test.rs:66:19:66:21 | row | test.rs:66:13:66:21 | ... + ... | provenance | MaD:11 |
6266
| test.rs:66:19:66:21 | row | test.rs:66:13:66:21 | ... + ... | provenance | MaD:12 |
6367
| test.rs:66:19:66:21 | row | test.rs:66:13:66:21 | ... + ... | provenance | MaD:15 |
68+
| test.rs:70:22:70:31 | query_fold | test.rs:70:83:70:105 | ...: ... | provenance | Src:MaD:2 |
69+
| test.rs:70:83:70:105 | ...: ... | test.rs:71:17:71:18 | id | provenance | |
70+
| test.rs:70:83:70:105 | ...: ... | test.rs:72:17:72:20 | name | provenance | |
71+
| test.rs:70:83:70:105 | ...: ... | test.rs:73:17:73:19 | age | provenance | |
72+
| test.rs:71:17:71:18 | id | test.rs:74:18:74:19 | id | provenance | |
73+
| test.rs:72:17:72:20 | name | test.rs:75:18:75:21 | name | provenance | |
74+
| test.rs:73:17:73:19 | age | test.rs:76:18:76:20 | age | provenance | |
6475
| test.rs:105:13:105:14 | v1 | test.rs:106:14:106:15 | v1 | provenance | |
6576
| test.rs:105:24:105:33 | row.get(...) [Some] | test.rs:105:24:105:42 | ... .unwrap() | provenance | MaD:16 |
6677
| test.rs:105:24:105:42 | ... .unwrap() | test.rs:105:13:105:14 | v1 | provenance | |
@@ -81,6 +92,10 @@ edges
8192
| test.rs:114:28:114:35 | take_opt | test.rs:114:24:114:38 | row.take_opt(...) [Some, Ok] | provenance | Src:MaD:10 |
8293
| test.rs:135:22:135:30 | query_map | test.rs:137:14:137:24 | ...: i64 | provenance | Src:MaD:5 |
8394
| test.rs:137:14:137:24 | ...: i64 | test.rs:138:22:138:27 | values | provenance | |
95+
| test.rs:142:22:142:30 | query_map | test.rs:144:14:144:39 | ...: ... | provenance | Src:MaD:5 |
96+
| test.rs:144:14:144:39 | ...: ... | test.rs:145:22:145:29 | values.0 | provenance | |
97+
| test.rs:144:14:144:39 | ...: ... | test.rs:146:22:146:29 | values.1 | provenance | |
98+
| test.rs:144:14:144:39 | ...: ... | test.rs:147:22:147:29 | values.2 | provenance | |
8499
| test.rs:151:13:151:17 | total | test.rs:155:14:155:18 | total | provenance | |
85100
| test.rs:151:21:154:10 | conn.query_fold(...) [future, Ok] | test.rs:151:21:154:16 | await ... [Ok] | provenance | |
86101
| test.rs:151:21:154:16 | await ... [Ok] | test.rs:151:21:154:17 | TryExpr | provenance | |
@@ -93,6 +108,13 @@ edges
93108
| test.rs:153:19:153:21 | row | test.rs:153:13:153:21 | ... + ... | provenance | MaD:11 |
94109
| test.rs:153:19:153:21 | row | test.rs:153:13:153:21 | ... + ... | provenance | MaD:12 |
95110
| test.rs:153:19:153:21 | row | test.rs:153:13:153:21 | ... + ... | provenance | MaD:15 |
111+
| test.rs:157:22:157:31 | query_fold | test.rs:157:83:157:105 | ...: ... | provenance | Src:MaD:4 |
112+
| test.rs:157:83:157:105 | ...: ... | test.rs:158:17:158:18 | id | provenance | |
113+
| test.rs:157:83:157:105 | ...: ... | test.rs:159:17:159:20 | name | provenance | |
114+
| test.rs:157:83:157:105 | ...: ... | test.rs:160:17:160:19 | age | provenance | |
115+
| test.rs:158:17:158:18 | id | test.rs:161:18:161:19 | id | provenance | |
116+
| test.rs:159:17:159:20 | name | test.rs:162:18:162:21 | name | provenance | |
117+
| test.rs:160:17:160:19 | age | test.rs:163:18:163:20 | age | provenance | |
96118
nodes
97119
| test.rs:18:13:18:14 | v1 | semmle.label | v1 |
98120
| test.rs:18:24:18:33 | row.get(...) [Some] | semmle.label | row.get(...) [Some] |
@@ -135,6 +157,11 @@ nodes
135157
| test.rs:48:22:48:30 | query_map | semmle.label | query_map |
136158
| test.rs:50:14:50:24 | ...: i64 | semmle.label | ...: i64 |
137159
| test.rs:51:22:51:27 | values | semmle.label | values |
160+
| test.rs:55:22:55:30 | query_map | semmle.label | query_map |
161+
| test.rs:57:14:57:39 | ...: ... | semmle.label | ...: ... |
162+
| test.rs:58:22:58:29 | values.0 | semmle.label | values.0 |
163+
| test.rs:59:22:59:29 | values.1 | semmle.label | values.1 |
164+
| test.rs:60:22:60:29 | values.2 | semmle.label | values.2 |
138165
| test.rs:64:13:64:17 | total | semmle.label | total |
139166
| test.rs:64:21:67:10 | conn.query_fold(...) [Ok] | semmle.label | conn.query_fold(...) [Ok] |
140167
| test.rs:64:21:67:11 | TryExpr | semmle.label | TryExpr |
@@ -145,6 +172,14 @@ nodes
145172
| test.rs:66:13:66:21 | ... + ... | semmle.label | ... + ... |
146173
| test.rs:66:19:66:21 | row | semmle.label | row |
147174
| test.rs:68:14:68:18 | total | semmle.label | total |
175+
| test.rs:70:22:70:31 | query_fold | semmle.label | query_fold |
176+
| test.rs:70:83:70:105 | ...: ... | semmle.label | ...: ... |
177+
| test.rs:71:17:71:18 | id | semmle.label | id |
178+
| test.rs:72:17:72:20 | name | semmle.label | name |
179+
| test.rs:73:17:73:19 | age | semmle.label | age |
180+
| test.rs:74:18:74:19 | id | semmle.label | id |
181+
| test.rs:75:18:75:21 | name | semmle.label | name |
182+
| test.rs:76:18:76:20 | age | semmle.label | age |
148183
| test.rs:105:13:105:14 | v1 | semmle.label | v1 |
149184
| test.rs:105:24:105:33 | row.get(...) [Some] | semmle.label | row.get(...) [Some] |
150185
| test.rs:105:24:105:42 | ... .unwrap() | semmle.label | ... .unwrap() |
@@ -170,6 +205,11 @@ nodes
170205
| test.rs:135:22:135:30 | query_map | semmle.label | query_map |
171206
| test.rs:137:14:137:24 | ...: i64 | semmle.label | ...: i64 |
172207
| test.rs:138:22:138:27 | values | semmle.label | values |
208+
| test.rs:142:22:142:30 | query_map | semmle.label | query_map |
209+
| test.rs:144:14:144:39 | ...: ... | semmle.label | ...: ... |
210+
| test.rs:145:22:145:29 | values.0 | semmle.label | values.0 |
211+
| test.rs:146:22:146:29 | values.1 | semmle.label | values.1 |
212+
| test.rs:147:22:147:29 | values.2 | semmle.label | values.2 |
173213
| test.rs:151:13:151:17 | total | semmle.label | total |
174214
| test.rs:151:21:154:10 | conn.query_fold(...) [future, Ok] | semmle.label | conn.query_fold(...) [future, Ok] |
175215
| test.rs:151:21:154:16 | await ... [Ok] | semmle.label | await ... [Ok] |
@@ -181,6 +221,14 @@ nodes
181221
| test.rs:153:13:153:21 | ... + ... | semmle.label | ... + ... |
182222
| test.rs:153:19:153:21 | row | semmle.label | row |
183223
| test.rs:155:14:155:18 | total | semmle.label | total |
224+
| test.rs:157:22:157:31 | query_fold | semmle.label | query_fold |
225+
| test.rs:157:83:157:105 | ...: ... | semmle.label | ...: ... |
226+
| test.rs:158:17:158:18 | id | semmle.label | id |
227+
| test.rs:159:17:159:20 | name | semmle.label | name |
228+
| test.rs:160:17:160:19 | age | semmle.label | age |
229+
| test.rs:161:18:161:19 | id | semmle.label | id |
230+
| test.rs:162:18:162:21 | name | semmle.label | name |
231+
| test.rs:163:18:163:20 | age | semmle.label | age |
184232
subpaths
185233
testFailures
186234
#select
@@ -192,12 +240,24 @@ testFailures
192240
| test.rs:41:14:41:70 | ... .unwrap() | test.rs:41:42:41:44 | get | test.rs:41:14:41:70 | ... .unwrap() | $@ | test.rs:41:42:41:44 | get | get |
193241
| test.rs:44:22:44:22 | v | test.rs:40:27:40:35 | exec_iter | test.rs:44:22:44:22 | v | $@ | test.rs:40:27:40:35 | exec_iter | exec_iter |
194242
| test.rs:51:22:51:27 | values | test.rs:48:22:48:30 | query_map | test.rs:51:22:51:27 | values | $@ | test.rs:48:22:48:30 | query_map | query_map |
243+
| test.rs:58:22:58:29 | values.0 | test.rs:55:22:55:30 | query_map | test.rs:58:22:58:29 | values.0 | $@ | test.rs:55:22:55:30 | query_map | query_map |
244+
| test.rs:59:22:59:29 | values.1 | test.rs:55:22:55:30 | query_map | test.rs:59:22:59:29 | values.1 | $@ | test.rs:55:22:55:30 | query_map | query_map |
245+
| test.rs:60:22:60:29 | values.2 | test.rs:55:22:55:30 | query_map | test.rs:60:22:60:29 | values.2 | $@ | test.rs:55:22:55:30 | query_map | query_map |
195246
| test.rs:65:18:65:20 | row | test.rs:64:26:64:35 | query_fold | test.rs:65:18:65:20 | row | $@ | test.rs:64:26:64:35 | query_fold | query_fold |
196247
| test.rs:68:14:68:18 | total | test.rs:64:26:64:35 | query_fold | test.rs:68:14:68:18 | total | $@ | test.rs:64:26:64:35 | query_fold | query_fold |
248+
| test.rs:74:18:74:19 | id | test.rs:70:22:70:31 | query_fold | test.rs:74:18:74:19 | id | $@ | test.rs:70:22:70:31 | query_fold | query_fold |
249+
| test.rs:75:18:75:21 | name | test.rs:70:22:70:31 | query_fold | test.rs:75:18:75:21 | name | $@ | test.rs:70:22:70:31 | query_fold | query_fold |
250+
| test.rs:76:18:76:20 | age | test.rs:70:22:70:31 | query_fold | test.rs:76:18:76:20 | age | $@ | test.rs:70:22:70:31 | query_fold | query_fold |
197251
| test.rs:106:14:106:15 | v1 | test.rs:105:28:105:30 | get | test.rs:106:14:106:15 | v1 | $@ | test.rs:105:28:105:30 | get | get |
198252
| test.rs:109:14:109:15 | v2 | test.rs:108:28:108:34 | get_opt | test.rs:109:14:109:15 | v2 | $@ | test.rs:108:28:108:34 | get_opt | get_opt |
199253
| test.rs:112:14:112:15 | v3 | test.rs:111:28:111:31 | take | test.rs:112:14:112:15 | v3 | $@ | test.rs:111:28:111:31 | take | take |
200254
| test.rs:115:14:115:15 | v4 | test.rs:114:28:114:35 | take_opt | test.rs:115:14:115:15 | v4 | $@ | test.rs:114:28:114:35 | take_opt | take_opt |
201255
| test.rs:138:22:138:27 | values | test.rs:135:22:135:30 | query_map | test.rs:138:22:138:27 | values | $@ | test.rs:135:22:135:30 | query_map | query_map |
256+
| test.rs:145:22:145:29 | values.0 | test.rs:142:22:142:30 | query_map | test.rs:145:22:145:29 | values.0 | $@ | test.rs:142:22:142:30 | query_map | query_map |
257+
| test.rs:146:22:146:29 | values.1 | test.rs:142:22:142:30 | query_map | test.rs:146:22:146:29 | values.1 | $@ | test.rs:142:22:142:30 | query_map | query_map |
258+
| test.rs:147:22:147:29 | values.2 | test.rs:142:22:142:30 | query_map | test.rs:147:22:147:29 | values.2 | $@ | test.rs:142:22:142:30 | query_map | query_map |
202259
| test.rs:152:18:152:20 | row | test.rs:151:26:151:35 | query_fold | test.rs:152:18:152:20 | row | $@ | test.rs:151:26:151:35 | query_fold | query_fold |
203260
| test.rs:155:14:155:18 | total | test.rs:151:26:151:35 | query_fold | test.rs:155:14:155:18 | total | $@ | test.rs:151:26:151:35 | query_fold | query_fold |
261+
| test.rs:161:18:161:19 | id | test.rs:157:22:157:31 | query_fold | test.rs:161:18:161:19 | id | $@ | test.rs:157:22:157:31 | query_fold | query_fold |
262+
| test.rs:162:18:162:21 | name | test.rs:157:22:157:31 | query_fold | test.rs:162:18:162:21 | name | $@ | test.rs:157:22:157:31 | query_fold | query_fold |
263+
| test.rs:163:18:163:20 | age | test.rs:157:22:157:31 | query_fold | test.rs:163:18:163:20 | age | $@ | test.rs:157:22:157:31 | query_fold | query_fold |

0 commit comments

Comments
 (0)