Skip to content

Commit 378eb18

Browse files
authored
Merge branch 'main' into jca_signature_extensions
2 parents 579da1d + 1f2cca7 commit 378eb18

File tree

218 files changed

+3103
-2154
lines changed

Some content is hidden

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

218 files changed

+3103
-2154
lines changed

Cargo.lock

Lines changed: 75 additions & 63 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MODULE.bazel

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ use_repo(
9898
tree_sitter_extractors_deps = use_extension("//misc/bazel/3rdparty:tree_sitter_extractors_extension.bzl", "r")
9999
use_repo(
100100
tree_sitter_extractors_deps,
101-
"vendor_ts__anyhow-1.0.99",
101+
"vendor_ts__anyhow-1.0.100",
102102
"vendor_ts__argfile-0.2.1",
103103
"vendor_ts__chalk-ir-0.104.0",
104104
"vendor_ts__chrono-0.4.42",
105-
"vendor_ts__clap-4.5.47",
105+
"vendor_ts__clap-4.5.48",
106106
"vendor_ts__dunce-1.0.5",
107107
"vendor_ts__either-1.15.0",
108108
"vendor_ts__encoding-0.2.33",
@@ -116,7 +116,7 @@ use_repo(
116116
"vendor_ts__num-traits-0.2.19",
117117
"vendor_ts__num_cpus-1.17.0",
118118
"vendor_ts__proc-macro2-1.0.101",
119-
"vendor_ts__quote-1.0.40",
119+
"vendor_ts__quote-1.0.41",
120120
"vendor_ts__ra_ap_base_db-0.0.301",
121121
"vendor_ts__ra_ap_cfg-0.0.301",
122122
"vendor_ts__ra_ap_hir-0.0.301",
@@ -135,17 +135,17 @@ use_repo(
135135
"vendor_ts__ra_ap_vfs-0.0.301",
136136
"vendor_ts__rand-0.9.2",
137137
"vendor_ts__rayon-1.11.0",
138-
"vendor_ts__regex-1.11.2",
139-
"vendor_ts__serde-1.0.219",
140-
"vendor_ts__serde_json-1.0.143",
141-
"vendor_ts__serde_with-3.14.0",
138+
"vendor_ts__regex-1.11.3",
139+
"vendor_ts__serde-1.0.228",
140+
"vendor_ts__serde_json-1.0.145",
141+
"vendor_ts__serde_with-3.14.1",
142142
"vendor_ts__syn-2.0.106",
143-
"vendor_ts__toml-0.9.5",
143+
"vendor_ts__toml-0.9.7",
144144
"vendor_ts__tracing-0.1.41",
145145
"vendor_ts__tracing-flame-0.2.0",
146146
"vendor_ts__tracing-subscriber-0.3.20",
147147
"vendor_ts__tree-sitter-0.25.9",
148-
"vendor_ts__tree-sitter-embedded-template-0.23.2",
148+
"vendor_ts__tree-sitter-embedded-template-0.25.0",
149149
"vendor_ts__tree-sitter-json-0.24.8",
150150
"vendor_ts__tree-sitter-ql-0.23.1",
151151
"vendor_ts__tree-sitter-ruby-0.23.1",

cpp/ql/lib/semmle/code/cpp/Element.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ElementBase extends @element {
8787
*/
8888
class Element extends ElementBase {
8989
/** Gets the primary file where this element occurs. */
90+
pragma[nomagic]
9091
File getFile() { result = this.getLocation().getFile() }
9192

9293
/**
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: breaking
3+
---
4+
* The member predicate `writesField` on `DataFlow::Write` now uses the post-update node for `base` when that is the node being updated, which is in all cases except initializing a struct literal. A new member predicate `writesFieldPreUpdate` has been added for cases where this behaviour is not desired.
5+
* The member predicate `writesElement` on `DataFlow::Write` now uses the post-update node for `base` when that is the node being updated, which is in all cases except initializing an array/slice/map literal. A new member predicate `writesElementPreUpdate` has been added for cases where this behaviour is not desired.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* The shape of the Go data-flow graph has changed. Previously for code like `x := def(); use1(x); use2(x)`, there would be edges from the definition of `x` to each use. Now there is an edge from the definition to the first use, then another from the first use to the second, and so on. This means that data-flow barriers work differently - flow will not reach any uses after the barrier node. Where this is not desired it may be be necessary to add an additional flow step to propagate the flow forward. Additionally, when a variable may be subject to a side-effect, such as updating an array, passing a pointer to a function that might write through it or writing to a field of a struct, there is now a dedicated post-update node representing the variable after this side-effect has taken place. Previously post-update nodes were aliases for either a variable's definition, or were equal to the pre-update node. This led to backwards steps in the data-flow graph, which could cause false positives. For example, in the previous code there would be an edge from `x` in `use2(x)` back to the definition of `x`. If we define our sources as any argument of `use2` and our sinks as any argument of `use1` then this would lead to a false positive path. Now there are distinct post-update nodes and no backwards edge to the definition, so we will not find this false positive path.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* For the query `go/unvalidated-url-redirection`, when untrusted data is assigned to the `Host` field of a `url.URL` struct, we consider the whole struct untrusted. We now also include the case when this happens during struct initialization, for example `&url.URL{Host: untrustedData}`.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* The member predicate `writesComponent` on `DataFlow::Write` has been deprecated. Instead, use `writesFieldPreUpdate` and `writesElementPreUpdate`, or their new versions `writesField` and `writesElement`.

go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ module ControlFlow {
118118
/** Gets the left-hand side of this write. */
119119
IR::WriteTarget getLhs() { result = super.getLhs() }
120120

121+
private predicate isInitialization() { super.isInitialization() }
122+
121123
/** Gets the right-hand side of this write. */
122124
DataFlow::Node getRhs() { super.getRhs() = result.asInstruction() }
123125

@@ -132,49 +134,112 @@ module ControlFlow {
132134

133135
/**
134136
* Holds if this node sets the value of field `f` on `base` (or its implicit dereference) to
135-
* `rhs`.
137+
* `rhs`, where `base` represents the post-update value.
138+
*
139+
* For example, for the assignment `x.width = newWidth`, `base` is the post-update node of
140+
* either the data-flow node corresponding to `x` or (if `x` is a pointer) the data-flow node
141+
* corresponding to the implicit dereference `*x`, `f` is the field referenced by `width`, and
142+
* `rhs` is the data-flow node corresponding to `newWidth`. If this `WriteNode` is a struct
143+
* initialization then there is no post-update node and `base` is the struct literal being
144+
* initialized.
145+
*/
146+
predicate writesField(DataFlow::Node base, Field f, DataFlow::Node rhs) {
147+
exists(DataFlow::Node b | this.writesFieldPreUpdate(b, f, rhs) |
148+
this.isInitialization() and base = b
149+
or
150+
not this.isInitialization() and
151+
b = base.(DataFlow::PostUpdateNode).getPreUpdateNode()
152+
)
153+
}
154+
155+
/**
156+
* Holds if this node sets the value of field `f` on `base` (or its implicit dereference) to
157+
* `rhs`, where `base` represents the pre-update value.
136158
*
137159
* For example, for the assignment `x.width = newWidth`, `base` is either the data-flow node
138160
* corresponding to `x` or (if `x` is a pointer) the data-flow node corresponding to the
139-
* implicit dereference `*x`, `f` is the field referenced by `width`, and `rhs` is the data-flow
140-
* node corresponding to `newWidth`.
161+
* implicit dereference `*x`, `f` is the field referenced by `width`, and `rhs` is the
162+
* data-flow node corresponding to `newWidth`.
141163
*/
142-
predicate writesField(DataFlow::Node base, Field f, DataFlow::Node rhs) {
164+
predicate writesFieldPreUpdate(DataFlow::Node base, Field f, DataFlow::Node rhs) {
165+
this.writesFieldInsn(base.asInstruction(), f, rhs.asInstruction())
166+
}
167+
168+
private predicate writesFieldInsn(IR::Instruction base, Field f, IR::Instruction rhs) {
143169
exists(IR::FieldTarget trg | trg = super.getLhs() |
144170
(
145-
trg.getBase() = base.asInstruction() or
146-
trg.getBase() = MkImplicitDeref(base.asExpr())
171+
trg.getBase() = base or
172+
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
147173
) and
148174
trg.getField() = f and
149-
super.getRhs() = rhs.asInstruction()
175+
super.getRhs() = rhs
150176
)
151177
}
152178

153179
/**
154180
* Holds if this node sets the value of element `index` on `base` (or its implicit dereference)
155181
* to `rhs`.
156182
*
157-
* For example, for the assignment `xs[i] = v`, `base` is either the data-flow node
158-
* corresponding to `xs` or (if `xs` is a pointer) the data-flow node corresponding to the
159-
* implicit dereference `*xs`, `index` is the data-flow node corresponding to `i`, and `rhs`
160-
* is the data-flow node corresponding to `base`.
183+
* For example, for the assignment `xs[i] = v`, `base` is the post-update node of the data-flow
184+
* node corresponding to `xs` or (if `xs` is a pointer) the implicit dereference `*xs`, `index`
185+
* is the data-flow node corresponding to `i`, and `rhs` is the data-flow node corresponding to
186+
* `base`. If this `WriteNode` corresponds to the initialization of an array/slice/map then
187+
* there is no need for a post-update node and `base` is the array/slice/map literal being
188+
* initialized.
161189
*/
162190
predicate writesElement(DataFlow::Node base, DataFlow::Node index, DataFlow::Node rhs) {
191+
exists(DataFlow::Node b | this.writesElementPreUpdate(b, index, rhs) |
192+
this.isInitialization() and base = b
193+
or
194+
not this.isInitialization() and
195+
b = base.(DataFlow::PostUpdateNode).getPreUpdateNode()
196+
)
197+
}
198+
199+
/**
200+
* Holds if this node sets the value of element `index` on `base` (or its implicit dereference)
201+
* to `rhs`.
202+
*
203+
* For example, for the assignment `xs[i] = v`, `base` is the post-update node of the data-flow
204+
* node corresponding to `xs` or (if `xs` is a pointer) the implicit dereference `*xs`, `index`
205+
* is the data-flow node corresponding to `i`, and `rhs` is the data-flow node corresponding to
206+
* `base`. If this `WriteNode` corresponds to the initialization of an array/slice/map then
207+
* there is no need for a post-update node and `base` is the array/slice/map literal being
208+
* initialized.
209+
*/
210+
predicate writesElementPreUpdate(DataFlow::Node base, DataFlow::Node index, DataFlow::Node rhs) {
211+
this.writesElementInsn(base.asInstruction(), index.asInstruction(), rhs.asInstruction())
212+
}
213+
214+
private predicate writesElementInsn(
215+
IR::Instruction base, IR::Instruction index, IR::Instruction rhs
216+
) {
163217
exists(IR::ElementTarget trg | trg = super.getLhs() |
164218
(
165-
trg.getBase() = base.asInstruction() or
166-
trg.getBase() = MkImplicitDeref(base.asExpr())
219+
trg.getBase() = base or
220+
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
167221
) and
168-
trg.getIndex() = index.asInstruction() and
169-
super.getRhs() = rhs.asInstruction()
222+
trg.getIndex() = index and
223+
super.getRhs() = rhs
170224
)
171225
}
172226

227+
/**
228+
* DEPRECATED: Use the disjunct of `writesElement` and `writesField`, or `writesFieldPreUpdate`
229+
* and `writesElementPreUpdate`, instead.
230+
*
231+
* Holds if this node sets any field or element of `base` (or its implicit dereference) to
232+
* `rhs`, where `base` represents the pre-update value.
233+
*/
234+
deprecated predicate writesComponent(DataFlow::Node base, DataFlow::Node rhs) {
235+
this.writesElementPreUpdate(base, _, rhs) or this.writesFieldPreUpdate(base, _, rhs)
236+
}
237+
173238
/**
174239
* Holds if this node sets any field or element of `base` to `rhs`.
175240
*/
176-
predicate writesComponent(DataFlow::Node base, DataFlow::Node rhs) {
177-
this.writesElement(base, _, rhs) or this.writesField(base, _, rhs)
241+
predicate writesComponentInstruction(IR::Instruction base, IR::Instruction rhs) {
242+
this.writesElementInsn(base, _, rhs) or this.writesFieldInsn(base, _, rhs)
178243
}
179244
}
180245

go/ql/lib/semmle/go/controlflow/IR.qll

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,18 +430,25 @@ module IR {
430430
*/
431431
class WriteInstruction extends Instruction {
432432
WriteTarget lhs;
433+
Boolean initialization;
433434

434435
WriteInstruction() {
435-
lhs = MkLhs(this, _)
436-
or
437-
lhs = MkLiteralElementTarget(this)
436+
(
437+
lhs = MkLhs(this, _)
438+
or
439+
lhs = MkResultWriteTarget(this)
440+
) and
441+
initialization = false
438442
or
439-
lhs = MkResultWriteTarget(this)
443+
lhs = MkLiteralElementTarget(this) and initialization = true
440444
}
441445

442446
/** Gets the target to which this instruction writes. */
443447
WriteTarget getLhs() { result = lhs }
444448

449+
/** Holds if this instruction initializes a literal. */
450+
predicate isInitialization() { initialization = true }
451+
445452
/** Gets the instruction computing the value this instruction writes. */
446453
Instruction getRhs() { none() }
447454

go/ql/lib/semmle/go/dataflow/SSA.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ class SsaDefinition extends TSsaDefinition {
166166
) {
167167
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
168168
}
169+
170+
/**
171+
* Gets the first instruction that the value of this `SsaDefinition` can
172+
* reach without passing through any other instructions, but possibly through
173+
* phi nodes.
174+
*/
175+
IR::Instruction getAFirstUse() { firstUse(this, result) }
169176
}
170177

171178
/**
@@ -410,3 +417,12 @@ DataFlow::Node getASimilarReadNode(DataFlow::Node node) {
410417
result = readFields.similar().getAUse()
411418
)
412419
}
420+
421+
/**
422+
* Gets an instruction such that `pred` and `result` form an adjacent
423+
* use-use-pair of the same`SsaSourceVariable`, that is, the value read in
424+
* `pred` can reach `result` without passing through any other use or any SSA
425+
* definition of the variable except for phi nodes and uncertain implicit
426+
* updates.
427+
*/
428+
IR::Instruction getAnAdjacentUse(IR::Instruction pred) { adjacentUseUse(pred, result) }

0 commit comments

Comments
 (0)