Merge branch 'main' into convert

This commit is contained in:
Geoffrey White
2025-09-26 14:11:04 +01:00
24 changed files with 1058 additions and 257 deletions

3
.gitignore vendored
View File

@@ -76,3 +76,6 @@ node_modules/
# some upgrade/downgrade checks create these files
**/upgrades/*/*.dbscheme.stats
**/downgrades/*/*.dbscheme.stats
# Mergetool files
*.orig

View File

@@ -126,7 +126,7 @@ Golang
""""""
* The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go.
* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\ ` to the beginning.
* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:``\`` to the beginning.
Java/Kotlin
"""""""""""

View File

@@ -10,7 +10,7 @@
* Data flow is now tracked through the `Promise.try` and `Array.prototype.with` functions.
* Query `js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test.
* The query `js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as `Object.keys()`.
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite.
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who [submitted the original experimental query](https://github.com/github/codeql/pull/14342)!
## 2.0.3

View File

@@ -10,4 +10,4 @@
* Data flow is now tracked through the `Promise.try` and `Array.prototype.with` functions.
* Query `js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test.
* The query `js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as `Object.keys()`.
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite.
* The query "Permissive CORS configuration" (`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who [submitted the original experimental query](https://github.com/github/codeql/pull/14342)!

View File

@@ -77,7 +77,7 @@ class CallableScopeTree extends StandardTree, PreOrderTree, PostOrderTree, Scope
override AstNode getChildNode(int i) {
i = 0 and
result = this.getParamList().getSelfParam()
result = this.getSelfParam()
or
result = this.getParam(i - 1)
or

View File

@@ -102,7 +102,7 @@ module Impl {
f = resolvePath(path) and
path.getSegment().getIdentifier().getText() = methodName and
exists(SelfParam self |
self = f.getParamList().getSelfParam() and
self = f.getSelfParam() and
if self.isRef() then selfIsRef = true else selfIsRef = false
)
)

View File

@@ -17,5 +17,25 @@ module Impl {
*/
class Callable extends Generated::Callable {
override Param getParam(int index) { result = this.getParamList().getParam(index) }
/**
* Gets the self parameter of this callable, if it exists.
*/
SelfParam getSelfParam() { result = this.getParamList().getSelfParam() }
/**
* Holds if `getSelfParam()` exists.
*/
predicate hasSelfParam() { exists(this.getSelfParam()) }
/**
* Gets the number of parameters of this callable, including `self` if it exists.
*/
int getNumberOfParamsInclSelf() {
exists(int arr |
arr = this.getNumberOfParams() and
if this.hasSelfParam() then result = arr + 1 else result = arr
)
}
}
}

View File

@@ -21,6 +21,13 @@ module Impl {
* ```
*/
class Union extends Generated::Union {
/** Gets the struct field named `name`, if any. */
pragma[nomagic]
StructField getStructField(string name) {
result = this.getStructFieldList().getAField() and
result.getName().getText() = name
}
override string toStringImpl() { result = "union " + this.getName().getText() }
}
}

View File

@@ -109,7 +109,7 @@ module Impl {
text = name.getText() and
// exclude self parameters from functions without a body as these are
// trait method declarations without implementations
not exists(Function f | not f.hasBody() and f.getParamList().getSelfParam() = sp)
not exists(Function f | not f.hasBody() and f.getSelfParam() = sp)
)
or
exists(IdentPat pat |

View File

@@ -4,6 +4,7 @@
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
private import codeql.rust.internal.CachedStages
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
private import codeql.util.Option
@@ -604,7 +605,13 @@ private class EnumItemNode extends TypeItemNode instanceof Enum {
}
}
private class VariantItemNode extends ItemNode instanceof Variant {
/** An item that can be referenced with arguments. */
abstract class ParameterizableItemNode extends ItemNode {
/** Gets the arity this item. */
abstract int getArity();
}
private class VariantItemNode extends ParameterizableItemNode instanceof Variant {
override string getName() { result = Variant.super.getName().getText() }
override Namespace getNamespace() {
@@ -617,6 +624,8 @@ private class VariantItemNode extends ItemNode instanceof Variant {
override Visibility getVisibility() { result = super.getEnum().getVisibility() }
override int getArity() { result = super.getFieldList().(TupleFieldList).getNumberOfFields() }
override predicate hasCanonicalPath(Crate c) { this.hasCanonicalPathPrefix(c) }
bindingset[c]
@@ -638,7 +647,7 @@ private class VariantItemNode extends ItemNode instanceof Variant {
}
}
class FunctionItemNode extends AssocItemNode instanceof Function {
class FunctionItemNode extends AssocItemNode, ParameterizableItemNode instanceof Function {
override string getName() { result = Function.super.getName().getText() }
override predicate hasImplementation() { Function.super.hasImplementation() }
@@ -648,6 +657,8 @@ class FunctionItemNode extends AssocItemNode instanceof Function {
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
override Visibility getVisibility() { result = Function.super.getVisibility() }
override int getArity() { result = super.getNumberOfParamsInclSelf() }
}
abstract class ImplOrTraitItemNode extends ItemNode {
@@ -712,8 +723,10 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
TypeParamItemNode getBlanketImplementationTypeParam() { result = this.resolveSelfTy() }
/**
* Holds if this impl block is a blanket implementation. That is, the
* Holds if this impl block is a [blanket implementation][1]. That is, the
* implementation targets a generic parameter of the impl block.
*
* [1]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
*/
predicate isBlanketImplementation() { exists(this.getBlanketImplementationTypeParam()) }
@@ -865,7 +878,7 @@ private class ImplItemNodeImpl extends ImplItemNode {
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
}
private class StructItemNode extends TypeItemNode instanceof Struct {
private class StructItemNode extends TypeItemNode, ParameterizableItemNode instanceof Struct {
override string getName() { result = Struct.super.getName().getText() }
override Namespace getNamespace() {
@@ -877,6 +890,8 @@ private class StructItemNode extends TypeItemNode instanceof Struct {
override Visibility getVisibility() { result = Struct.super.getVisibility() }
override int getArity() { result = super.getFieldList().(TupleFieldList).getNumberOfFields() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
override predicate hasCanonicalPath(Crate c) { this.hasCanonicalPathPrefix(c) }
@@ -1687,6 +1702,14 @@ private ItemNode resolvePathCand(RelevantPath path) {
or
not pathUsesNamespace(path, _) and
not path = any(MacroCall mc).getPath()
) and
(
not path = CallExprImpl::getFunctionPath(_)
or
exists(CallExpr ce |
path = CallExprImpl::getFunctionPath(ce) and
result.(ParameterizableItemNode).getArity() = ce.getNumberOfArgs()
)
)
}

View File

@@ -42,11 +42,14 @@ newtype TType =
TStruct(Struct s) or
TEnum(Enum e) or
TTrait(Trait t) or
TUnion(Union u) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(ImplTraitTypeRepr impl) or
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
TSliceType() or
TNeverType() or
TPtrType() or
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
@@ -57,7 +60,8 @@ newtype TType =
} or
TRefTypeParameter() or
TSelfTypeParameter(Trait t) or
TSliceTypeParameter()
TSliceTypeParameter() or
TPtrTypeParameter()
private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
implTrait.isInReturnPos() and
@@ -224,6 +228,31 @@ class TraitType extends Type, TTrait {
override Location getLocation() { result = trait.getLocation() }
}
/** A union type. */
class UnionType extends StructOrEnumType, TUnion {
private Union union;
UnionType() { this = TUnion(union) }
override ItemNode asItemNode() { result = union }
override StructField getStructField(string name) { result = union.getStructField(name) }
override TupleField getTupleField(int i) { none() }
override TypeParameter getPositionalTypeParameter(int i) {
result = TTypeParamTypeParameter(union.getGenericParamList().getTypeParam(i))
}
override TypeMention getTypeParameterDefault(int i) {
result = union.getGenericParamList().getTypeParam(i).getDefaultType()
}
override string toString() { result = union.getName().getText() }
override Location getLocation() { result = union.getLocation() }
}
/**
* An array type.
*
@@ -374,6 +403,33 @@ class SliceType extends Type, TSliceType {
override Location getLocation() { result instanceof EmptyLocation }
}
class NeverType extends Type, TNeverType {
override StructField getStructField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getPositionalTypeParameter(int i) { none() }
override string toString() { result = "!" }
override Location getLocation() { result instanceof EmptyLocation }
}
class PtrType extends Type, TPtrType {
override StructField getStructField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getPositionalTypeParameter(int i) {
i = 0 and
result = TPtrTypeParameter()
}
override string toString() { result = "*" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** A type parameter. */
abstract class TypeParameter extends Type {
override StructField getStructField(string name) { none() }
@@ -529,6 +585,12 @@ class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
override Location getLocation() { result instanceof EmptyLocation }
}
class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
override string toString() { result = "*T" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* The implicit `Self` type parameter of a trait, that refers to the
* implementing type of the trait.

View File

@@ -99,6 +99,11 @@ private module Input1 implements InputSig1<Location> {
id1 = 0 and
id2 = 2
or
tp0 instanceof PtrTypeParameter and
kind = 0 and
id1 = 0 and
id2 = 3
or
kind = 1 and
id1 = 0 and
id2 =
@@ -230,7 +235,7 @@ module Consistency {
// Suppress the inconsistency if `n` is a self parameter and the type
// mention for the self type has multiple types for a path.
not exists(ImplItemNode impl, TypePath selfTypePath |
n = impl.getAnAssocItem().(Function).getParamList().getSelfParam() and
n = impl.getAnAssocItem().(Function).getSelfParam() and
strictcount(impl.(Impl).getSelfTy().(TypeMention).resolveTypeAt(selfTypePath)) > 1
)
}
@@ -948,7 +953,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
)
or
exists(SelfParam self |
self = pragma[only_bind_into](this.getParamList().getSelfParam()) and
self = pragma[only_bind_into](this.getSelfParam()) and
dpos.isSelf() and
result = inferAnnotatedType(self, path) // `self` parameter with type annotation
)
@@ -972,7 +977,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
exists(ImplOrTraitItemNode i |
this = i.getAnAssocItem() and
dpos.isSelf() and
not this.getParamList().hasSelfParam()
not this.hasSelfParam()
|
result = TSelfTypeParameter(i) and
path.isEmpty()
@@ -1900,7 +1905,7 @@ private predicate methodCandidate(Type type, string name, int arity, Impl impl)
type = impl.getSelfTy().(TypeMention).resolveType() and
exists(Function f |
f = impl.(ImplItemNode).getASuccessor(name) and
f.getParamList().hasSelfParam() and
f.hasSelfParam() and
arity = f.getParamList().getNumberOfParams()
)
}
@@ -2222,7 +2227,7 @@ private module BlanketImplementation {
) {
isCanonicalImpl(impl) and
blanketImplementationTraitBound(impl, traitBound) and
f.getParamList().hasSelfParam() and
f.hasSelfParam() and
arity = f.getParamList().getNumberOfParams() and
(
f = impl.getAssocItem(name)
@@ -2332,7 +2337,7 @@ private Function resolveMethodCallTarget(MethodCall mc) {
pragma[nomagic]
private predicate assocFuncResolutionDependsOnArgument(Function f, Impl impl, int pos) {
functionResolutionDependsOnArgument(impl, _, f, pos, _, _) and
not f.getParamList().hasSelfParam()
not f.hasSelfParam()
}
private class FunctionCallExpr extends CallImpl::CallExprCall {

View File

@@ -241,6 +241,8 @@ class NonAliasPathTypeMention extends PathTypeMention {
else result = TTrait(trait)
)
or
result = TUnion(resolved)
or
result = TTypeParamTypeParameter(resolved)
or
result = TAssociatedTypeTypeParameter(resolved)
@@ -387,3 +389,19 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList {
)
}
}
class NeverTypeReprMention extends TypeMention, NeverTypeRepr {
override Type resolveTypeAt(TypePath path) { result = TNeverType() and path.isEmpty() }
}
class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr {
override Type resolveTypeAt(TypePath path) {
path.isEmpty() and
result = TPtrType()
or
exists(TypePath suffix |
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TPtrTypeParameter(), suffix)
)
}
}

View File

@@ -1,2 +0,0 @@
illFormedTypeMention
| macro_expansion.rs:99:7:99:19 | MyDeriveUnion |

View File

@@ -2250,6 +2250,7 @@ inferType
| main.rs:1127:43:1127:82 | MacroExpr | | main.rs:1124:15:1124:17 | Snd |
| main.rs:1127:50:1127:81 | "PairNone has no second elemen... | | file://:0:0:0:0 | & |
| main.rs:1127:50:1127:81 | "PairNone has no second elemen... | &T | {EXTERNAL LOCATION} | str |
| main.rs:1127:50:1127:81 | ...::panic_fmt(...) | | file://:0:0:0:0 | ! |
| main.rs:1127:50:1127:81 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
| main.rs:1127:50:1127:81 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
| main.rs:1127:50:1127:81 | MacroExpr | | main.rs:1124:15:1124:17 | Snd |
@@ -2261,6 +2262,7 @@ inferType
| main.rs:1128:43:1128:81 | MacroExpr | | main.rs:1124:15:1124:17 | Snd |
| main.rs:1128:50:1128:80 | "PairFst has no second element... | | file://:0:0:0:0 | & |
| main.rs:1128:50:1128:80 | "PairFst has no second element... | &T | {EXTERNAL LOCATION} | str |
| main.rs:1128:50:1128:80 | ...::panic_fmt(...) | | file://:0:0:0:0 | ! |
| main.rs:1128:50:1128:80 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
| main.rs:1128:50:1128:80 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
| main.rs:1128:50:1128:80 | MacroExpr | | main.rs:1124:15:1124:17 | Snd |

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "test"
version = "0.0.1"

View File

@@ -1,7 +1,2 @@
multipleCallTargets
| test_cipher.rs:20:27:20:48 | ...::new(...) |
| test_cipher.rs:26:27:26:48 | ...::new(...) |
| test_cipher.rs:29:27:29:48 | ...::new(...) |
| test_cipher.rs:36:30:36:59 | ...::new(...) |
| test_cipher.rs:39:30:39:63 | ...::new(...) |
| test_cipher.rs:114:23:114:50 | ...::new(...) |

View File

@@ -0,0 +1,3 @@
multipleCallTargets
| test.rs:117:9:117:20 | ptr.is_null() |
| test.rs:117:9:117:21 | ptr.is_null() |

View File

@@ -0,0 +1,7 @@
multipleCallTargets
| main.rs:242:44:242:78 | ... .cast() |
| main.rs:245:44:245:78 | ... .cast() |
| main.rs:248:44:248:78 | ... .cast() |
| main.rs:251:14:251:48 | ... .cast() |
| main.rs:254:14:254:48 | ... .cast() |
| main.rs:257:14:257:48 | ... .cast() |

View File

@@ -1,10 +0,0 @@
multipleCallTargets
| test_cipher.rs:15:30:15:77 | ...::new(...) |
| test_cipher.rs:19:30:19:80 | ...::new(...) |
| test_cipher.rs:22:30:22:98 | ...::new(...) |
| test_cipher.rs:26:30:26:101 | ...::new(...) |
| test_cipher.rs:30:30:30:102 | ...::new(...) |
| test_cipher.rs:38:30:38:81 | ...::new(...) |
| test_cipher.rs:42:30:42:80 | ...::new(...) |
| test_cipher.rs:47:30:47:85 | ...::new(...) |
| test_cipher.rs:51:31:51:83 | ...::new(...) |

View File

@@ -0,0 +1,726 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aead"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
"crypto-common",
"generic-array",
]
[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "aes-gcm-siv"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"polyval",
"subtle",
"zeroize",
]
[[package]]
name = "anyhow"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "biscotti"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddb6f28a3d15d18cace7a8010282a4d9cee1452dcd33f5861c173b4a31095b79"
dependencies = [
"aes-gcm-siv",
"anyhow",
"base64",
"hkdf",
"hmac",
"jiff",
"percent-encoding",
"rand 0.9.2",
"serde",
"sha2",
"subtle",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cfb-mode"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330"
dependencies = [
"cipher",
]
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "cookie"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [
"aes-gcm",
"base64",
"hmac",
"rand 0.8.5",
"sha2",
"subtle",
"time",
"version_check",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"rand_core 0.6.4",
"typenum",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
]
[[package]]
name = "deranged"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.1+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.7+wasi-0.2.4",
]
[[package]]
name = "ghash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "inout"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
"generic-array",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
"windows-sys",
]
[[package]]
name = "jiff-static"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "jiff-tzdb"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
[[package]]
name = "jiff-tzdb-platform"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
dependencies = [
"jiff-tzdb",
]
[[package]]
name = "libc"
version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "polyval"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "portable-atomic"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rabbit"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "931a21d28d73d260f6743712e0f04292413fc6d004bb278bb9022302221a05d5"
dependencies = [
"cipher",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.16",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.3",
]
[[package]]
name = "serde"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "test"
version = "0.0.1"
dependencies = [
"aes",
"aes-gcm",
"base64",
"biscotti",
"cfb-mode",
"cipher",
"cookie",
"getrandom 0.2.16",
"getrandom 0.3.3",
"rabbit",
]
[[package]]
name = "time"
version = "0.3.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]]
name = "time-macros"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle",
]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.7+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
dependencies = [
"wasip2",
]
[[package]]
name = "wasip2"
version = "1.0.1+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

View File

@@ -1,15 +1,9 @@
#select
| test_cipher.rs:18:29:18:36 | [0u8; 16] | test_cipher.rs:18:29:18:36 | [0u8; 16] | test_cipher.rs:19:30:19:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:19:30:19:47 | ...::new | a key |
| test_cipher.rs:18:29:18:36 | [0u8; 16] | test_cipher.rs:18:29:18:36 | [0u8; 16] | test_cipher.rs:19:30:19:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:19:30:19:47 | ...::new | a key |
| test_cipher.rs:25:29:25:36 | [0u8; 16] | test_cipher.rs:25:29:25:36 | [0u8; 16] | test_cipher.rs:26:30:26:40 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:26:30:26:40 | ...::new | a key |
| test_cipher.rs:25:29:25:36 | [0u8; 16] | test_cipher.rs:25:29:25:36 | [0u8; 16] | test_cipher.rs:26:30:26:40 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:26:30:26:40 | ...::new | a key |
| test_cipher.rs:29:29:29:36 | [0u8; 16] | test_cipher.rs:29:29:29:36 | [0u8; 16] | test_cipher.rs:30:30:30:40 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:30:30:30:40 | ...::new | an initialization vector |
| test_cipher.rs:29:29:29:36 | [0u8; 16] | test_cipher.rs:29:29:29:36 | [0u8; 16] | test_cipher.rs:30:30:30:40 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:30:30:30:40 | ...::new | an initialization vector |
| test_cipher.rs:37:27:37:74 | [...] | test_cipher.rs:37:27:37:74 | [...] | test_cipher.rs:38:30:38:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:38:30:38:47 | ...::new | a key |
| test_cipher.rs:37:27:37:74 | [...] | test_cipher.rs:37:27:37:74 | [...] | test_cipher.rs:38:30:38:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:38:30:38:47 | ...::new | a key |
| test_cipher.rs:41:29:41:76 | [...] | test_cipher.rs:41:29:41:76 | [...] | test_cipher.rs:42:30:42:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:42:30:42:47 | ...::new | a key |
| test_cipher.rs:41:29:41:76 | [...] | test_cipher.rs:41:29:41:76 | [...] | test_cipher.rs:42:30:42:47 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:42:30:42:47 | ...::new | a key |
| test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:51:31:51:48 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:51:31:51:48 | ...::new | a key |
| test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:51:31:51:48 | ...::new | This hard-coded value is used as $@. | test_cipher.rs:51:31:51:48 | ...::new | a key |
| test_cipher.rs:73:19:73:26 | [0u8; 32] | test_cipher.rs:73:19:73:26 | [0u8; 32] | test_cipher.rs:74:23:74:44 | ...::new_from_slice | This hard-coded value is used as $@. | test_cipher.rs:74:23:74:44 | ...::new_from_slice | a key |
| test_cookie.rs:17:28:17:34 | [0; 64] | test_cookie.rs:17:28:17:34 | [0; 64] | test_cookie.rs:18:16:18:24 | ...::from | This hard-coded value is used as $@. | test_cookie.rs:18:16:18:24 | ...::from | a key |
@@ -21,38 +15,32 @@ edges
| test_cipher.rs:18:28:18:36 | &... [&ref] | test_cipher.rs:18:9:18:14 | const1 [&ref] | provenance | |
| test_cipher.rs:18:29:18:36 | [0u8; 16] | test_cipher.rs:18:28:18:36 | &... [&ref] | provenance | |
| test_cipher.rs:19:49:19:79 | ...::from_slice(...) [&ref] | test_cipher.rs:19:30:19:47 | ...::new | provenance | MaD:3 Sink:MaD:3 |
| test_cipher.rs:19:49:19:79 | ...::from_slice(...) [&ref] | test_cipher.rs:19:30:19:47 | ...::new | provenance | MaD:5 Sink:MaD:5 |
| test_cipher.rs:19:73:19:78 | const1 [&ref] | test_cipher.rs:19:49:19:79 | ...::from_slice(...) [&ref] | provenance | MaD:10 |
| test_cipher.rs:19:73:19:78 | const1 [&ref] | test_cipher.rs:19:49:19:79 | ...::from_slice(...) [&ref] | provenance | MaD:9 |
| test_cipher.rs:25:9:25:14 | const4 [&ref] | test_cipher.rs:26:66:26:71 | const4 [&ref] | provenance | |
| test_cipher.rs:25:28:25:36 | &... [&ref] | test_cipher.rs:25:9:25:14 | const4 [&ref] | provenance | |
| test_cipher.rs:25:29:25:36 | [0u8; 16] | test_cipher.rs:25:28:25:36 | &... [&ref] | provenance | |
| test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | test_cipher.rs:26:30:26:40 | ...::new | provenance | MaD:3 Sink:MaD:3 |
| test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | test_cipher.rs:26:30:26:40 | ...::new | provenance | MaD:5 Sink:MaD:5 |
| test_cipher.rs:26:66:26:71 | const4 [&ref] | test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | provenance | MaD:10 |
| test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | test_cipher.rs:26:30:26:40 | ...::new | provenance | MaD:4 Sink:MaD:4 |
| test_cipher.rs:26:66:26:71 | const4 [&ref] | test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | provenance | MaD:9 |
| test_cipher.rs:29:9:29:14 | const5 [&ref] | test_cipher.rs:30:95:30:100 | const5 [&ref] | provenance | |
| test_cipher.rs:29:28:29:36 | &... [&ref] | test_cipher.rs:29:9:29:14 | const5 [&ref] | provenance | |
| test_cipher.rs:29:29:29:36 | [0u8; 16] | test_cipher.rs:29:28:29:36 | &... [&ref] | provenance | |
| test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | test_cipher.rs:30:30:30:40 | ...::new | provenance | MaD:4 Sink:MaD:4 |
| test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | test_cipher.rs:30:30:30:40 | ...::new | provenance | MaD:6 Sink:MaD:6 |
| test_cipher.rs:30:95:30:100 | const5 [&ref] | test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | provenance | MaD:10 |
| test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | test_cipher.rs:30:30:30:40 | ...::new | provenance | MaD:5 Sink:MaD:5 |
| test_cipher.rs:30:95:30:100 | const5 [&ref] | test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | provenance | MaD:9 |
| test_cipher.rs:37:9:37:14 | const7 | test_cipher.rs:38:74:38:79 | const7 | provenance | |
| test_cipher.rs:37:27:37:74 | [...] | test_cipher.rs:37:9:37:14 | const7 | provenance | |
| test_cipher.rs:38:49:38:80 | ...::from_slice(...) [&ref] | test_cipher.rs:38:30:38:47 | ...::new | provenance | MaD:3 Sink:MaD:3 |
| test_cipher.rs:38:49:38:80 | ...::from_slice(...) [&ref] | test_cipher.rs:38:30:38:47 | ...::new | provenance | MaD:5 Sink:MaD:5 |
| test_cipher.rs:38:73:38:79 | &const7 [&ref] | test_cipher.rs:38:49:38:80 | ...::from_slice(...) [&ref] | provenance | MaD:10 |
| test_cipher.rs:38:73:38:79 | &const7 [&ref] | test_cipher.rs:38:49:38:80 | ...::from_slice(...) [&ref] | provenance | MaD:9 |
| test_cipher.rs:38:74:38:79 | const7 | test_cipher.rs:38:73:38:79 | &const7 [&ref] | provenance | |
| test_cipher.rs:41:9:41:14 | const8 [&ref] | test_cipher.rs:42:73:42:78 | const8 [&ref] | provenance | |
| test_cipher.rs:41:28:41:76 | &... [&ref] | test_cipher.rs:41:9:41:14 | const8 [&ref] | provenance | |
| test_cipher.rs:41:29:41:76 | [...] | test_cipher.rs:41:28:41:76 | &... [&ref] | provenance | |
| test_cipher.rs:42:49:42:79 | ...::from_slice(...) [&ref] | test_cipher.rs:42:30:42:47 | ...::new | provenance | MaD:3 Sink:MaD:3 |
| test_cipher.rs:42:49:42:79 | ...::from_slice(...) [&ref] | test_cipher.rs:42:30:42:47 | ...::new | provenance | MaD:5 Sink:MaD:5 |
| test_cipher.rs:42:73:42:78 | const8 [&ref] | test_cipher.rs:42:49:42:79 | ...::from_slice(...) [&ref] | provenance | MaD:10 |
| test_cipher.rs:42:73:42:78 | const8 [&ref] | test_cipher.rs:42:49:42:79 | ...::from_slice(...) [&ref] | provenance | MaD:9 |
| test_cipher.rs:50:9:50:15 | const10 [element] | test_cipher.rs:51:75:51:81 | const10 [element] | provenance | |
| test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:50:37:50:54 | ...::zeroed(...) [element] | provenance | Src:MaD:8 |
| test_cipher.rs:50:37:50:52 | ...::zeroed | test_cipher.rs:50:37:50:54 | ...::zeroed(...) [element] | provenance | Src:MaD:7 |
| test_cipher.rs:50:37:50:54 | ...::zeroed(...) [element] | test_cipher.rs:50:9:50:15 | const10 [element] | provenance | |
| test_cipher.rs:51:50:51:82 | ...::from_slice(...) [&ref, element] | test_cipher.rs:51:31:51:48 | ...::new | provenance | MaD:3 Sink:MaD:3 Sink:MaD:3 |
| test_cipher.rs:51:50:51:82 | ...::from_slice(...) [&ref, element] | test_cipher.rs:51:31:51:48 | ...::new | provenance | MaD:5 Sink:MaD:5 Sink:MaD:5 |
| test_cipher.rs:51:74:51:81 | &const10 [&ref, element] | test_cipher.rs:51:50:51:82 | ...::from_slice(...) [&ref, element] | provenance | MaD:10 |
| test_cipher.rs:51:74:51:81 | &const10 [&ref, element] | test_cipher.rs:51:50:51:82 | ...::from_slice(...) [&ref, element] | provenance | MaD:9 |
| test_cipher.rs:51:75:51:81 | const10 [element] | test_cipher.rs:51:74:51:81 | &const10 [&ref, element] | provenance | |
| test_cipher.rs:73:9:73:14 | const2 [&ref] | test_cipher.rs:74:46:74:51 | const2 [&ref] | provenance | |
| test_cipher.rs:73:18:73:26 | &... [&ref] | test_cipher.rs:73:9:73:14 | const2 [&ref] | provenance | |
@@ -60,58 +48,53 @@ edges
| test_cipher.rs:74:46:74:51 | const2 [&ref] | test_cipher.rs:74:23:74:44 | ...::new_from_slice | provenance | MaD:1 Sink:MaD:1 |
| test_cookie.rs:17:9:17:14 | array1 | test_cookie.rs:18:27:18:32 | array1 | provenance | |
| test_cookie.rs:17:28:17:34 | [0; 64] | test_cookie.rs:17:9:17:14 | array1 | provenance | |
| test_cookie.rs:18:26:18:32 | &array1 [&ref] | test_cookie.rs:18:16:18:24 | ...::from | provenance | MaD:7 Sink:MaD:7 |
| test_cookie.rs:18:26:18:32 | &array1 [&ref] | test_cookie.rs:18:16:18:24 | ...::from | provenance | MaD:6 Sink:MaD:6 |
| test_cookie.rs:18:27:18:32 | array1 | test_cookie.rs:18:26:18:32 | &array1 [&ref] | provenance | |
| test_cookie.rs:21:9:21:14 | array2 | test_cookie.rs:22:27:22:32 | array2 | provenance | |
| test_cookie.rs:21:28:21:34 | [0; 64] | test_cookie.rs:21:9:21:14 | array2 | provenance | |
| test_cookie.rs:22:26:22:32 | &array2 [&ref] | test_cookie.rs:22:16:22:24 | ...::from | provenance | MaD:7 Sink:MaD:7 |
| test_cookie.rs:22:26:22:32 | &array2 [&ref] | test_cookie.rs:22:16:22:24 | ...::from | provenance | MaD:6 Sink:MaD:6 |
| test_cookie.rs:22:27:22:32 | array2 | test_cookie.rs:22:26:22:32 | &array2 [&ref] | provenance | |
| test_cookie.rs:38:9:38:14 | array2 | test_cookie.rs:42:34:42:39 | array2 | provenance | |
| test_cookie.rs:38:18:38:37 | ...::from(...) | test_cookie.rs:38:9:38:14 | array2 | provenance | |
| test_cookie.rs:38:28:38:36 | [0u8; 64] | test_cookie.rs:38:18:38:37 | ...::from(...) | provenance | MaD:9 |
| test_cookie.rs:38:28:38:36 | [0u8; 64] | test_cookie.rs:38:18:38:37 | ...::from(...) | provenance | MaD:8 |
| test_cookie.rs:42:34:42:39 | array2 | test_cookie.rs:42:14:42:32 | ...::from | provenance | MaD:2 Sink:MaD:2 |
| test_cookie.rs:49:9:49:14 | array3 [element] | test_cookie.rs:53:34:53:39 | array3 [element] | provenance | |
| test_cookie.rs:49:23:49:25 | 0u8 | test_cookie.rs:49:23:49:29 | ...::from_elem(...) [element] | provenance | MaD:11 |
| test_cookie.rs:49:23:49:25 | 0u8 | test_cookie.rs:49:23:49:29 | ...::from_elem(...) [element] | provenance | MaD:10 |
| test_cookie.rs:49:23:49:29 | ...::from_elem(...) [element] | test_cookie.rs:49:9:49:14 | array3 [element] | provenance | |
| test_cookie.rs:53:34:53:39 | array3 [element] | test_cookie.rs:53:14:53:32 | ...::from | provenance | MaD:2 Sink:MaD:2 |
models
| 1 | Sink: <_ as crypto_common::KeyInit>::new_from_slice; Argument[0]; credentials-key |
| 2 | Sink: <biscotti::crypto::master::Key>::from; Argument[0]; credentials-key |
| 3 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyInit>::new; Argument[0]; credentials-key |
| 4 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyInit>::new; Argument[1]; credentials-iv |
| 5 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyIvInit>::new; Argument[0]; credentials-key |
| 6 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyIvInit>::new; Argument[1]; credentials-iv |
| 7 | Sink: <cookie::secure::key::Key>::from; Argument[0].Reference; credentials-key |
| 8 | Source: core::mem::zeroed; ReturnValue.Element; constant-source |
| 9 | Summary: <_ as core::convert::From>::from; Argument[0]; ReturnValue; taint |
| 10 | Summary: <generic_array::GenericArray>::from_slice; Argument[0].Reference; ReturnValue.Reference; value |
| 11 | Summary: alloc::vec::from_elem; Argument[0]; ReturnValue.Element; value |
| 4 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyIvInit>::new; Argument[0]; credentials-key |
| 5 | Sink: <cipher::stream_wrapper::StreamCipherCoreWrapper as crypto_common::KeyIvInit>::new; Argument[1]; credentials-iv |
| 6 | Sink: <cookie::secure::key::Key>::from; Argument[0].Reference; credentials-key |
| 7 | Source: core::mem::zeroed; ReturnValue.Element; constant-source |
| 8 | Summary: <_ as core::convert::From>::from; Argument[0]; ReturnValue; taint |
| 9 | Summary: <generic_array::GenericArray>::from_slice; Argument[0].Reference; ReturnValue.Reference; value |
| 10 | Summary: alloc::vec::from_elem; Argument[0]; ReturnValue.Element; value |
nodes
| test_cipher.rs:18:9:18:14 | const1 [&ref] | semmle.label | const1 [&ref] |
| test_cipher.rs:18:28:18:36 | &... [&ref] | semmle.label | &... [&ref] |
| test_cipher.rs:18:29:18:36 | [0u8; 16] | semmle.label | [0u8; 16] |
| test_cipher.rs:19:30:19:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:19:30:19:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:19:49:19:79 | ...::from_slice(...) [&ref] | semmle.label | ...::from_slice(...) [&ref] |
| test_cipher.rs:19:73:19:78 | const1 [&ref] | semmle.label | const1 [&ref] |
| test_cipher.rs:25:9:25:14 | const4 [&ref] | semmle.label | const4 [&ref] |
| test_cipher.rs:25:28:25:36 | &... [&ref] | semmle.label | &... [&ref] |
| test_cipher.rs:25:29:25:36 | [0u8; 16] | semmle.label | [0u8; 16] |
| test_cipher.rs:26:30:26:40 | ...::new | semmle.label | ...::new |
| test_cipher.rs:26:30:26:40 | ...::new | semmle.label | ...::new |
| test_cipher.rs:26:42:26:72 | ...::from_slice(...) [&ref] | semmle.label | ...::from_slice(...) [&ref] |
| test_cipher.rs:26:66:26:71 | const4 [&ref] | semmle.label | const4 [&ref] |
| test_cipher.rs:29:9:29:14 | const5 [&ref] | semmle.label | const5 [&ref] |
| test_cipher.rs:29:28:29:36 | &... [&ref] | semmle.label | &... [&ref] |
| test_cipher.rs:29:29:29:36 | [0u8; 16] | semmle.label | [0u8; 16] |
| test_cipher.rs:30:30:30:40 | ...::new | semmle.label | ...::new |
| test_cipher.rs:30:30:30:40 | ...::new | semmle.label | ...::new |
| test_cipher.rs:30:72:30:101 | ...::from_slice(...) [&ref] | semmle.label | ...::from_slice(...) [&ref] |
| test_cipher.rs:30:95:30:100 | const5 [&ref] | semmle.label | const5 [&ref] |
| test_cipher.rs:37:9:37:14 | const7 | semmle.label | const7 |
| test_cipher.rs:37:27:37:74 | [...] | semmle.label | [...] |
| test_cipher.rs:38:30:38:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:38:30:38:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:38:49:38:80 | ...::from_slice(...) [&ref] | semmle.label | ...::from_slice(...) [&ref] |
| test_cipher.rs:38:73:38:79 | &const7 [&ref] | semmle.label | &const7 [&ref] |
| test_cipher.rs:38:74:38:79 | const7 | semmle.label | const7 |
@@ -119,14 +102,12 @@ nodes
| test_cipher.rs:41:28:41:76 | &... [&ref] | semmle.label | &... [&ref] |
| test_cipher.rs:41:29:41:76 | [...] | semmle.label | [...] |
| test_cipher.rs:42:30:42:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:42:30:42:47 | ...::new | semmle.label | ...::new |
| test_cipher.rs:42:49:42:79 | ...::from_slice(...) [&ref] | semmle.label | ...::from_slice(...) [&ref] |
| test_cipher.rs:42:73:42:78 | const8 [&ref] | semmle.label | const8 [&ref] |
| test_cipher.rs:50:9:50:15 | const10 [element] | semmle.label | const10 [element] |
| test_cipher.rs:50:37:50:52 | ...::zeroed | semmle.label | ...::zeroed |
| test_cipher.rs:50:37:50:54 | ...::zeroed(...) [element] | semmle.label | ...::zeroed(...) [element] |
| test_cipher.rs:51:31:51:48 | ...::new | semmle.label | ...::new |
| test_cipher.rs:51:31:51:48 | ...::new | semmle.label | ...::new |
| test_cipher.rs:51:50:51:82 | ...::from_slice(...) [&ref, element] | semmle.label | ...::from_slice(...) [&ref, element] |
| test_cipher.rs:51:74:51:81 | &const10 [&ref, element] | semmle.label | &const10 [&ref, element] |
| test_cipher.rs:51:75:51:81 | const10 [element] | semmle.label | const10 [element] |

View File

@@ -80,6 +80,9 @@ signature module InputSig<LocationSig Location, TypSig ControlFlowNode, TypSig B
/** Gets a textual representation of this value. */
string toString();
/** Holds if this value represents a single concrete value. */
predicate isSingleton();
/**
* Gets the dual value. Examples of dual values include:
* - null vs. not null
@@ -265,23 +268,17 @@ module Make<
)
}
/** Holds if `gv1` is a strict subset of `gv2`. */
bindingset[gv1, gv2]
private predicate smaller(GuardValue gv1, GuardValue gv2) {
disjointValues(gv1, gv2.getDualValue()) and
gv1 != gv2
}
/**
* Holds if the value of `def` is `gv`.
*
* If multiple values apply, then we only include the most precise ones.
* If multiple values apply, including a singleton, then we only include the
* singleton.
*/
private predicate ssaHasValue(SsaWriteDefinition def, GuardValue gv) {
exists(Expr e |
def.getDefinition() = e and
exprHasValue(e, gv) and
not exists(GuardValue gv0 | exprHasValue(e, gv0) and smaller(gv0, gv))
(any(GuardValue gv0 | exprHasValue(e, gv0)).isSingleton() implies gv.isSingleton())
)
}
@@ -292,157 +289,51 @@ module Make<
}
pragma[nomagic]
private predicate initSsaValue0(SourceVariable var, BasicBlock bb, SsaDefinition t, GuardValue val) {
private predicate initSsaValue0(
SourceVariable var, BasicBlock bb, SsaDefinition t, GuardValue val, boolean isSingleton
) {
ssaLiveAtEndOfBlock(var, t, bb) and
(
ssaControls(t, bb, val)
or
ssaHasValue(t, val)
)
) and
if val.isSingleton() then isSingleton = true else isSingleton = false
}
/**
* Holds if the value of `t` in `bb` is `val` and that `t` is live at the
* end of `bb`.
*
* If multiple values apply, then we only include the most precise ones.
* If multiple values apply, including a singleton, then we only include the
* singleton.
*
* The underlying variable of `t` is `var`.
*/
private predicate initSsaValue(SourceVariable var, BasicBlock bb, SsaDefinition t, GuardValue val) {
initSsaValue0(var, bb, t, val) and
not exists(GuardValue val0 | initSsaValue0(var, bb, t, val0) and smaller(val0, val))
}
private predicate possibleValue(SourceVariable var, GuardValue gv) {
exists(SsaDefinition def | def.getSourceVariable() = var |
ssaHasValue(def, gv)
or
ssaControlsBranchEdge(def, _, _, gv)
exists(boolean isSingleton |
initSsaValue0(var, bb, t, val, isSingleton) and
(initSsaValue0(var, bb, t, _, true) implies isSingleton = true)
)
}
private predicate possibleRangeBound(SourceVariable var, int bound, boolean upper) {
exists(GuardValue gv | possibleValue(var, gv) and gv.isIntRange(bound, upper))
}
private module GuardValueOption = Option<GuardValue>;
private predicate possibleClosedRange(SourceVariable var, int low, int high) {
possibleRangeBound(var, low, false) and
possibleRangeBound(var, high, true) and
low < high
}
private newtype TGuardValueExt =
AnyValue() or
BaseValue(GuardValue gv) { possibleValue(_, gv) } or
IntRange(int low, int high) { possibleClosedRange(_, low, high) }
private class GuardValueExt extends TGuardValueExt {
string toString() {
result = "Any" and this = AnyValue()
or
result = this.asBase().toString()
or
exists(int low, int high |
this = IntRange(low, high) and result = "[" + low + ", " + high + "]"
)
}
GuardValue asBase() { this = BaseValue(result) }
}
private class TGuardValueOrAny = AnyValue or BaseValue;
private class GuardValueOrAny extends GuardValueExt, TGuardValueOrAny { }
private GuardValueExt mkRange(int low, int high) {
result = IntRange(low, high)
or
low = high and
result.asBase().asIntValue() = low
}
private GuardValueExt intersectBase1(GuardValue gv1, GuardValue gv2) {
exists(SourceVariable var |
possibleValue(var, gv1) and
possibleValue(var, gv2)
|
smaller(gv1, gv2) and result.asBase() = gv1
or
exists(int low, int high |
gv1.isIntRange(low, false) and
gv2.isIntRange(high, true) and
result = mkRange(low, high)
)
or
exists(int bound, boolean upper, int d |
gv1.isIntRange(bound, upper) and
gv2.getDualValue().asIntValue() = bound and
result.asBase().isIntRange(bound + d, upper)
|
upper = true and d = -1
or
upper = false and d = 1
)
)
}
private GuardValueExt intersectBase2(GuardValueExt v1, GuardValue v2) {
result = intersectBase1(v1.asBase(), v2)
or
result = intersectBase1(v2, v1.asBase())
}
private class GuardValueOption = GuardValueOption::Option;
/**
* Gets the best constraint of `v1` and `v2`. If both are non-singletons,
* then we arbitrarily choose `v1`. This operation approximates intersection.
*/
bindingset[v1, v2]
pragma[inline_late]
private GuardValueExt intersectRange(GuardValueExt v1, GuardValue v2) {
exists(int low, int high | v1 = IntRange(low, high) |
exists(int bound, boolean upper | v2.isIntRange(bound, upper) |
upper = true and result = mkRange(low, high.minimum(bound))
or
upper = false and result = mkRange(low.maximum(bound), high)
)
or
exists(int k |
v2.asIntValue() = k and
result.asBase() = v2 and
low <= k and
k <= high
)
or
not v2.isIntRange(_, _) and not exists(v2.asIntValue()) and result = v1
)
}
bindingset[v1, v2]
pragma[inline_late]
private GuardValueExt intersect(GuardValueExt v1, GuardValue v2) {
v1 = AnyValue() and result.asBase() = v2
or
result = intersectBase2(v1, v2)
or
result = v1 and
v1 instanceof BaseValue and
not exists(intersectBase2(v1, v2))
or
result = intersectRange(v1, v2)
}
bindingset[v1, gv2]
private predicate disjointValuesExt(GuardValueExt v1, GuardValue gv2) {
disjointValues(v1.asBase(), gv2)
or
exists(int low, int high | v1 = IntRange(low, high) |
gv2.asIntValue() < low
or
high < gv2.asIntValue()
or
exists(int bound, boolean upper | gv2.isIntRange(bound, upper) |
upper = true and bound < low
or
upper = false and high < bound
)
)
private GuardValueOption intersect(GuardValueOption v1, GuardValue v2) {
if v2.isSingleton()
then result.asSome() = v2
else
if v1.isNone()
then result.asSome() = v2
else result = v1
}
/** An input configuration for control flow reachability. */
@@ -558,6 +449,7 @@ module Make<
* Holds if the edge from `bb1` to `bb2` implies that `def` has a value
* that is considered a barrier.
*/
pragma[nomagic]
private predicate ssaValueBarrierEdge(SsaDefinition def, BasicBlock bb1, BasicBlock bb2) {
exists(GuardValue v |
ssaControlsBranchEdge(def, bb1, bb2, v) and
@@ -565,6 +457,11 @@ module Make<
)
}
pragma[nomagic]
private predicate phiBlock(BasicBlock bb, SourceVariable v) {
exists(SsaPhiNode phi | phi.getBasicBlock() = bb and phi.getSourceVariable() = v)
}
/** Holds if `def1` in `bb1` may step to `def2` in `bb2`. */
private predicate step(SsaDefinition def1, BasicBlock bb1, SsaDefinition def2, BasicBlock bb2) {
not sinkBlock(def1, bb1, _) and
@@ -577,7 +474,7 @@ module Make<
ssaRelevantAtEndOfBlock(def1, bb1) and
bb1.getASuccessor() = bb2 and
v = def1.getSourceVariable() and
not exists(SsaPhiNode phi | phi.getBasicBlock() = bb2 and phi.getSourceVariable() = v) and
not phiBlock(bb2, v) and
def1 = def2
)
or
@@ -687,8 +584,8 @@ module Make<
* Holds if the edge from `bb1` to `bb2` implies that `def` has the value
* `gv` and that the edge is relevant for computing reachability of `src`.
*
* If multiple values may be implied by this edge, then we only include the
* most precise ones.
* If multiple values may be implied by this edge, including a singleton,
* then we only include the singleton.
*
* The underlying variable of `t` is `var`.
*/
@@ -697,7 +594,11 @@ module Make<
BasicBlock bb2
) {
ssaControlsBranchEdge(t, bb1, bb2, gv) and
not exists(GuardValue gv0 | ssaControlsBranchEdge(t, bb1, bb2, gv0) and smaller(gv0, gv)) and
(
any(GuardValue gv0 | ssaControlsBranchEdge(t, bb1, bb2, gv0)).isSingleton()
implies
gv.isSingleton()
) and
pathEdge(src, bb1, bb2) and
t.getSourceVariable() = var
}
@@ -711,18 +612,36 @@ module Make<
exists(BasicBlock pred | pathEdge(src, pred, entry) and entry.strictlyDominates(pred))
}
/**
* Gets either `gv` or its dual value. This is intended as a mostly unique
* representation of the set of values `gv` and `gv.getDualValue()`.
*/
private GuardValue getPrimary(GuardValue gv) {
exists(GuardValue dual | dual = gv.getDualValue() |
if dual.isSingleton() then result = dual else result = gv
)
}
/**
* Holds if precision may be improved by splitting control flow on the
* value of `var` during the reachability computation of `src`.
*
* The `condgv`/`condgv.getDualValue()` separation of the values of `var`
* determines whether a possibly relevant edge may be taken or not.
*/
private predicate relevantSplit(SourceVariable src, SourceVariable var) {
private predicate relevantSplit(SourceVariable src, SourceVariable var, GuardValue condgv) {
// `var` may be a relevant split if we encounter 2+ conditional edges
// that imply information about `var`.
2 <= strictcount(BasicBlock bb1 | ssaControlsPathEdge(src, _, var, _, bb1, _))
exists(GuardValue gv |
ssaControlsPathEdge(src, _, var, gv, _, _) and
condgv = getPrimary(gv) and
2 <= strictcount(BasicBlock bb1 | ssaControlsPathEdge(src, _, var, _, bb1, _))
)
or
// Or if we encounter a conditional edge that imply a value that's
// incompatible with an initial or later assigned value.
exists(GuardValue gv1, GuardValue gv2, BasicBlock bb |
condgv = getPrimary(gv1) and
ssaControlsPathEdge(src, _, var, gv1, _, _) and
initSsaValue(var, bb, _, gv2) and
disjointValues(gv1, gv2) and
@@ -731,8 +650,11 @@ module Make<
or
// Or if we encounter a conditional edge in a loop that imply a value for
// `var` that may be unchanged from one iteration to the next.
exists(SsaDefinition def, BasicBlock bb1, BasicBlock bb2, BasicBlock loopEntry |
ssaControlsPathEdge(src, def, var, _, bb1, bb2) and
exists(
SsaDefinition def, BasicBlock bb1, BasicBlock bb2, BasicBlock loopEntry, GuardValue gv
|
ssaControlsPathEdge(src, def, var, gv, bb1, bb2) and
condgv = getPrimary(gv) and
loopEntryBlock(src, loopEntry) and
loopEntry.strictlyDominates(bb1) and
bb2.getASuccessor*() = loopEntry
@@ -755,25 +677,40 @@ module Make<
def = max(SsaDefinition d, int i | d.definesAt(var, bb, i) | d order by i)
}
/**
* Holds if `gv` is relatable to the `condgv`/`condgv.getDualValue()` pair
* in the sense that a conditional branch based on `condgv` may be
* determined by `gv`.
*/
bindingset[gv, condgv]
pragma[inline_late]
private predicate relatable(GuardValue gv, GuardValue condgv) {
disjointValues(gv, condgv) or
disjointValues(gv, condgv.getDualValue())
}
/**
* Holds if `bb1` to `bb2` is a relevant edge for computing reachability of
* `src`, and `var` is a relevant splitting variable that gets (re-)defined
* in `bb2` by `t`, which is not a phi node.
*
* `val` is the best known value for `t` in `bb2`.
* `val` is the best known value that is relatable to `condgv` for `t` in `bb2`.
*/
private predicate stepSsaValueRedef(
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t,
GuardValueOrAny val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
SsaDefinition t, GuardValueOption val
) {
pathEdge(src, bb1, bb2) and
relevantSplit(src, var) and
relevantSplit(src, var, condgv) and
lastDefInBlock(var, t, bb2) and
not t instanceof SsaPhiNode and
(
ssaHasValue(t, val.asBase())
exists(GuardValue gv |
ssaHasValue(t, gv) and
if relatable(gv, condgv) then val.asSome() = gv else val.isNone()
)
or
not ssaHasValue(t, _) and val = AnyValue()
not ssaHasValue(t, _) and val.isNone()
)
}
@@ -783,21 +720,25 @@ module Make<
* `t2`, in `bb2` taking input from `t1` along this edge. Furthermore,
* there is no further redefinition of `var` in `bb2`.
*
* `val` is the best value for `t1`/`t2` implied by taking this edge.
* `val` is the best value that is relatable to `condgv` for `t1`/`t2`
* implied by taking this edge.
*/
private predicate stepSsaValuePhi(
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t1,
SsaDefinition t2, GuardValueOrAny val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
SsaDefinition t1, SsaDefinition t2, GuardValueOption val
) {
pathEdge(src, bb1, bb2) and
relevantSplit(src, var) and
relevantSplit(src, var, condgv) and
lastDefInBlock(var, t2, bb2) and
t2.(SsaPhiNode).hasInputFromBlock(t1, bb1) and
(
ssaControlsPathEdge(src, t1, _, val.asBase(), bb1, bb2)
exists(GuardValue gv |
ssaControlsPathEdge(src, t1, _, gv, bb1, bb2) and
if relatable(gv, condgv) then val.asSome() = gv else val.isNone()
)
or
not ssaControlsPathEdge(src, t1, _, _, bb1, bb2) and
val = AnyValue()
val.isNone()
)
}
@@ -807,84 +748,94 @@ module Make<
* redefinition along this edge nor in `bb2`.
*
* Additionally, this edge implies that the SSA definition `t` of `var` has
* value `val`.
* value `val` and that `val` is relatable to `condgv`.
*/
private predicate stepSsaValueNoRedef(
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t,
GuardValue val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
SsaDefinition t, GuardValue val
) {
pathEdge(src, bb1, bb2) and
relevantSplit(src, var) and
relevantSplit(src, var, condgv) and
not lastDefInBlock(var, _, bb2) and
ssaControlsPathEdge(src, t, var, val, bb1, bb2)
ssaControlsPathEdge(src, t, var, val, bb1, bb2) and
relatable(val, condgv)
}
/**
* Holds if the source `srcDef` in `srcBb` may reach `def` in `bb`. The
* taken path takes splitting based on the value of `var` into account.
*
* When multiple `GuardValue`s can be chosen for `var`, we prioritize those
* that are relatable to `condgv`, as that will help determine whether a
* particular edge may be taken or not. Singleton values are prioritized
* highly as they are in principle relatable to every other `GuardValue`.
*
* The pair `(tracked, val)` is the current SSA definition and known value
* for `var` in `bb`.
*/
private predicate sourceReachesBlockWithTrackedVar(
SsaDefinition srcDef, BasicBlock srcBb, SsaDefinition def, BasicBlock bb, FinallyStack fs,
SsaDefOption tracked, GuardValueExt val, SourceVariable var
SsaDefOption tracked, GuardValueOption val, SourceVariable var, GuardValue condgv
) {
sourceBlock(srcDef, srcBb, _) and
def = srcDef and
bb = srcBb and
fs = TNil() and
relevantSplit(def.getSourceVariable(), var) and
relevantSplit(def.getSourceVariable(), var, condgv) and
(
// tracking variable is not yet live
not ssaLiveAtEndOfBlock(var, _, bb) and
tracked.isNone() and
val = AnyValue()
val.isNone()
or
// tracking variable is live but without known value
ssaLiveAtEndOfBlock(var, tracked.asSome(), bb) and
not initSsaValue(var, bb, _, _) and
val = AnyValue()
val.isNone()
or
// tracking variable has known value
initSsaValue(var, bb, tracked.asSome(), val.asBase())
// tracking variable has known value, track it if it is relatable to condgv
exists(GuardValue gv | initSsaValue(var, bb, tracked.asSome(), gv) |
if relatable(gv, condgv) then val.asSome() = gv else val.isNone()
)
)
or
exists(
SourceVariable src, SsaDefinition middef, BasicBlock midbb, FinallyStack midfs,
SsaDefOption tracked0, GuardValueExt val0
SsaDefOption tracked0, GuardValueOption val0
|
sourceReachesBlockWithTrackedVar(srcDef, srcBb, middef, midbb, midfs, tracked0, val0, var) and
sourceReachesBlockWithTrackedVar(srcDef, srcBb, middef, midbb, midfs, tracked0, val0, var,
condgv) and
src = srcDef.getSourceVariable() and
step(middef, midbb, def, bb) and
stepFinallyStack(midbb, bb, midfs, fs) and
pathBlock(src, bb) and
pathBlock(pragma[only_bind_into](src), bb) and
not exists(GuardValue gv |
ssaControlsPathEdge(src, tracked0.asSome(), _, gv, midbb, bb) and
disjointValuesExt(val0, gv)
disjointValues(val0.asSome(), gv)
)
|
// tracking variable is redefined
stepSsaValueRedef(src, midbb, bb, var, tracked.asSome(), val)
stepSsaValueRedef(src, midbb, bb, var, condgv, tracked.asSome(), val)
or
exists(GuardValueOrAny val1 |
exists(GuardValueOption val1 |
// tracking variable has a phi node, and maybe value information from the edge
stepSsaValuePhi(src, midbb, bb, var, tracked0.asSome(), tracked.asSome(), val1)
stepSsaValuePhi(src, midbb, bb, var, condgv, tracked0.asSome(), tracked.asSome(), val1)
|
val = val0 and val1 = AnyValue()
val = val0 and val1.isNone()
or
val = intersect(val0, val1.asBase())
val = intersect(val0, val1.asSome())
)
or
exists(GuardValue val1 |
// tracking variable is unchanged, and has value information from the edge
stepSsaValueNoRedef(src, midbb, bb, var, tracked0.asSome(), val1) and
stepSsaValueNoRedef(src, midbb, bb, var, condgv, tracked0.asSome(), val1) and
tracked = tracked0 and
val = intersect(val0, val1)
)
or
// tracking variable is unchanged, and has no value information from the edge
not lastDefInBlock(var, _, bb) and
not stepSsaValueNoRedef(src, midbb, bb, var, tracked0.asSome(), _) and
not stepSsaValueNoRedef(src, midbb, bb, var, condgv, tracked0.asSome(), _) and
tracked = tracked0 and
val = val0
)
@@ -903,8 +854,8 @@ module Make<
sourceReachesBlock(srcDef, srcBb, sinkDef, sinkBb, _) and
sinkBlock(sinkDef, sinkBb, sink) and
srcVar = srcDef.getSourceVariable() and
forall(SourceVariable t | relevantSplit(srcVar, t) |
sourceReachesBlockWithTrackedVar(srcDef, srcBb, sinkDef, sinkBb, _, _, _, t)
forall(SourceVariable t, GuardValue condgv | relevantSplit(srcVar, t, condgv) |
sourceReachesBlockWithTrackedVar(srcDef, srcBb, sinkDef, sinkBb, _, _, _, t, condgv)
)
)
}
@@ -920,8 +871,8 @@ module Make<
sourceBlock(srcDef, srcBb, src) and
sourceEscapesSink(srcDef, srcBb, escDef, escBb) and
srcVar = srcDef.getSourceVariable() and
forall(SourceVariable t | relevantSplit(srcVar, t) |
sourceReachesBlockWithTrackedVar(srcDef, srcBb, escDef, escBb, _, _, _, t)
forall(SourceVariable t, GuardValue condgv | relevantSplit(srcVar, t, condgv) |
sourceReachesBlockWithTrackedVar(srcDef, srcBb, escDef, escBb, _, _, _, t, condgv)
)
)
}

View File

@@ -259,6 +259,9 @@ module Make<
)
}
/** Holds if this value represents a single concrete value. */
predicate isSingleton() { this = TValue(_, true) }
/** Holds if this value represents `null`. */
predicate isNullValue() { this.isNullness(true) }