mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #20133 from paldepind/rust/type-inference-blanket-impl
Rust: Support blanket implementations
This commit is contained in:
@@ -648,6 +648,18 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
|
||||
|
||||
override Visibility getVisibility() { result = Impl.super.getVisibility() }
|
||||
|
||||
TypeParamItemNode getBlanketImplementationTypeParam() {
|
||||
result = this.resolveSelfTy() and
|
||||
// This impl block is not superseded by the expansion of an attribute macro.
|
||||
not exists(super.getAttributeMacroExpansion())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this impl block is a blanket implementation. That is, the
|
||||
* implementation targets a generic parameter of the impl block.
|
||||
*/
|
||||
predicate isBlanketImplementation() { exists(this.getBlanketImplementationTypeParam()) }
|
||||
|
||||
override predicate hasCanonicalPath(Crate c) { this.resolveSelfTy().hasCanonicalPathPrefix(c) }
|
||||
|
||||
/**
|
||||
@@ -1006,6 +1018,14 @@ final class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
|
||||
Path getABoundPath() { result = this.getTypeBoundAt(_, _).getTypeRepr().(PathTypeRepr).getPath() }
|
||||
|
||||
pragma[nomagic]
|
||||
ItemNode resolveBound(int index) {
|
||||
result =
|
||||
rank[index + 1](int i, int j |
|
||||
|
|
||||
resolvePath(this.getTypeBoundAt(i, j).getTypeRepr().(PathTypeRepr).getPath()) order by i, j
|
||||
)
|
||||
}
|
||||
|
||||
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1915,6 +1915,10 @@ private predicate methodCandidateTrait(Type type, Trait trait, string name, int
|
||||
methodCandidate(type, name, arity, impl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `mc` has `rootType` as the root type of the receiver and the target
|
||||
* method is named `name` and has arity `arity`
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate isMethodCall(MethodCall mc, Type rootType, string name, int arity) {
|
||||
rootType = mc.getTypeAt(TypePath::nil()) and
|
||||
@@ -2153,6 +2157,130 @@ private predicate methodCallHasImplCandidate(MethodCall mc, Impl impl) {
|
||||
else any()
|
||||
}
|
||||
|
||||
private module BlanketImplementation {
|
||||
private ImplItemNode getPotentialDuplicated(
|
||||
string fileName, string traitName, int arity, string tpName
|
||||
) {
|
||||
tpName = result.getBlanketImplementationTypeParam().getName() and
|
||||
fileName = result.getLocation().getFile().getBaseName() and
|
||||
traitName = result.resolveTraitTy().getName() and
|
||||
arity = result.resolveTraitTy().(Trait).getNumberOfGenericParams()
|
||||
}
|
||||
|
||||
private predicate duplicatedImpl(Impl impl1, Impl impl2) {
|
||||
exists(string fileName, string traitName, int arity, string tpName |
|
||||
impl1 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
|
||||
impl2 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
|
||||
impl1.getLocation().getFile().getAbsolutePath() <
|
||||
impl2.getLocation().getFile().getAbsolutePath()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl` is a canonical blanket implementation.
|
||||
*
|
||||
* Libraries can often occur several times in the database for different
|
||||
* library versions. This causes the same blanket implementations to exist
|
||||
* multiple times, and these add no useful information.
|
||||
*
|
||||
* We detect these duplicates based on some simple heuristics (same trait
|
||||
* name, file name, etc.). For these duplicates we select the one with the
|
||||
* greatest file name (which usually is also the one with the greatest library
|
||||
* version in the path) as the "canonical" implementation.
|
||||
*/
|
||||
private predicate isCanonicalImpl(Impl impl) {
|
||||
not duplicatedImpl(impl, _) and impl.(ImplItemNode).isBlanketImplementation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl` is a blanket implementation for a type parameter and
|
||||
* `traitBound` is the first non-trivial trait bound of that type parameter.
|
||||
*/
|
||||
private predicate blanketImplementationTraitBound(ImplItemNode impl, Trait traitBound) {
|
||||
traitBound =
|
||||
min(Trait trait, int i |
|
||||
trait = impl.getBlanketImplementationTypeParam().resolveBound(i) and
|
||||
// Exclude traits that are known to not narrow things down very much.
|
||||
not trait.getName().getText() =
|
||||
[
|
||||
"Sized", "Clone",
|
||||
// The auto traits
|
||||
"Send", "Sync", "Unpin", "UnwindSafe", "RefUnwindSafe"
|
||||
]
|
||||
|
|
||||
trait order by i
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl` is a relevant blanket implementation that requires the
|
||||
* trait `traitBound` and provides `f`, a method with name `name` and arity
|
||||
* `arity`.
|
||||
*/
|
||||
private predicate blanketImplementationMethod(
|
||||
ImplItemNode impl, Trait traitBound, string name, int arity, Function f
|
||||
) {
|
||||
isCanonicalImpl(impl) and
|
||||
blanketImplementationTraitBound(impl, traitBound) and
|
||||
f.getParamList().hasSelfParam() and
|
||||
arity = f.getParamList().getNumberOfParams() and
|
||||
(
|
||||
f = impl.getAssocItem(name)
|
||||
or
|
||||
// If the trait has a method with a default implementation, then that
|
||||
// target is interesting as well.
|
||||
not exists(impl.getAssocItem(name)) and
|
||||
f = impl.resolveTraitTy().getAssocItem(name)
|
||||
) and
|
||||
// If the method is already available through one of the trait bounds on the
|
||||
// type parameter (because they implement the trait targeted by the impl
|
||||
// block) then ignore it.
|
||||
not impl.getBlanketImplementationTypeParam().resolveABound().(TraitItemNode).getASuccessor(name) =
|
||||
f
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate methodCallMatchesBlanketImpl(
|
||||
MethodCall mc, Type t, ImplItemNode impl, Trait traitBound, Trait traitImpl, Function f
|
||||
) {
|
||||
// Only check method calls where we have ruled out inherent method targets.
|
||||
// Ideally we would also check if non-blanket method targets have been ruled
|
||||
// out.
|
||||
methodCallHasNoInherentTarget(mc) and
|
||||
exists(string name, int arity |
|
||||
isMethodCall(mc, t, name, arity) and
|
||||
blanketImplementationMethod(impl, traitBound, name, arity, f)
|
||||
) and
|
||||
traitImpl = impl.resolveTraitTy()
|
||||
}
|
||||
|
||||
private predicate relevantTraitVisible(Element mc, Trait trait) {
|
||||
methodCallMatchesBlanketImpl(mc, _, _, _, trait, _)
|
||||
}
|
||||
|
||||
module SatisfiesConstraintInput implements SatisfiesConstraintInputSig<MethodCall> {
|
||||
pragma[nomagic]
|
||||
predicate relevantConstraint(MethodCall mc, Type constraint) {
|
||||
exists(Trait traitBound, Trait traitImpl |
|
||||
methodCallMatchesBlanketImpl(mc, _, _, traitBound, traitImpl, _) and
|
||||
TraitIsVisible<relevantTraitVisible/2>::traitIsVisible(mc, traitImpl) and
|
||||
traitBound = constraint.(TraitType).getTrait()
|
||||
)
|
||||
}
|
||||
|
||||
predicate useUniversalConditions() { none() }
|
||||
}
|
||||
|
||||
predicate hasBlanketImpl(MethodCall mc, Type t, Impl impl, Trait traitBound, Function f) {
|
||||
SatisfiesConstraint<MethodCall, SatisfiesConstraintInput>::satisfiesConstraintType(mc,
|
||||
TTrait(traitBound), _, _) and
|
||||
methodCallMatchesBlanketImpl(mc, t, impl, traitBound, _, f)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
Function getMethodFromBlanketImpl(MethodCall mc) { hasBlanketImpl(mc, _, _, _, result) }
|
||||
}
|
||||
|
||||
/** Gets a method from an `impl` block that matches the method call `mc`. */
|
||||
pragma[nomagic]
|
||||
private Function getMethodFromImpl(MethodCall mc) {
|
||||
@@ -2188,6 +2316,8 @@ private Function resolveMethodCallTarget(MethodCall mc) {
|
||||
// The method comes from an `impl` block targeting the type of the receiver.
|
||||
result = getMethodFromImpl(mc)
|
||||
or
|
||||
result = BlanketImplementation::getMethodFromBlanketImpl(mc)
|
||||
or
|
||||
// The type of the receiver is a type parameter and the method comes from a
|
||||
// trait bound on the type parameter.
|
||||
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
|
||||
|
||||
@@ -1005,12 +1005,15 @@ readStep
|
||||
| main.rs:458:5:458:11 | mut_arr | file://:0:0:0:0 | element | main.rs:458:5:458:14 | mut_arr[1] |
|
||||
| main.rs:459:13:459:19 | mut_arr | file://:0:0:0:0 | element | main.rs:459:13:459:22 | mut_arr[1] |
|
||||
| main.rs:461:10:461:16 | mut_arr | file://:0:0:0:0 | element | main.rs:461:10:461:19 | mut_arr[0] |
|
||||
| main.rs:467:24:467:33 | [post] receiver for source(...) | file://:0:0:0:0 | &ref | main.rs:467:24:467:33 | [post] source(...) |
|
||||
| main.rs:468:9:468:20 | TuplePat | file://:0:0:0:0 | tuple.0 | main.rs:468:10:468:13 | cond |
|
||||
| main.rs:468:9:468:20 | TuplePat | file://:0:0:0:0 | tuple.1 | main.rs:468:16:468:19 | name |
|
||||
| main.rs:468:25:468:29 | names | file://:0:0:0:0 | element | main.rs:468:9:468:20 | TuplePat |
|
||||
| main.rs:470:41:470:67 | [post] \|...\| ... | main.rs:467:9:467:20 | captured default_name | main.rs:470:41:470:67 | [post] default_name |
|
||||
| main.rs:470:44:470:55 | [post] receiver for default_name | file://:0:0:0:0 | &ref | main.rs:470:44:470:55 | [post] default_name |
|
||||
| main.rs:470:44:470:55 | this | main.rs:467:9:467:20 | captured default_name | main.rs:470:44:470:55 | default_name |
|
||||
| main.rs:471:18:471:18 | [post] receiver for n | file://:0:0:0:0 | &ref | main.rs:471:18:471:18 | [post] n |
|
||||
| main.rs:494:13:494:13 | [post] receiver for a | file://:0:0:0:0 | &ref | main.rs:494:13:494:13 | [post] a |
|
||||
| main.rs:495:13:495:13 | [post] receiver for b | file://:0:0:0:0 | &ref | main.rs:495:13:495:13 | [post] b |
|
||||
| main.rs:496:18:496:18 | [post] receiver for b | file://:0:0:0:0 | &ref | main.rs:496:18:496:18 | [post] b |
|
||||
| main.rs:507:10:507:11 | vs | file://:0:0:0:0 | element | main.rs:507:10:507:14 | vs[0] |
|
||||
@@ -1110,8 +1113,11 @@ storeStep
|
||||
| main.rs:455:27:455:27 | 2 | file://:0:0:0:0 | element | main.rs:455:23:455:31 | [...] |
|
||||
| main.rs:455:30:455:30 | 3 | file://:0:0:0:0 | element | main.rs:455:23:455:31 | [...] |
|
||||
| main.rs:458:18:458:27 | source(...) | file://:0:0:0:0 | element | main.rs:458:5:458:11 | [post] mut_arr |
|
||||
| main.rs:467:24:467:33 | source(...) | file://:0:0:0:0 | &ref | main.rs:467:24:467:33 | receiver for source(...) |
|
||||
| main.rs:470:41:470:67 | default_name | main.rs:467:9:467:20 | captured default_name | main.rs:470:41:470:67 | \|...\| ... |
|
||||
| main.rs:470:44:470:55 | default_name | file://:0:0:0:0 | &ref | main.rs:470:44:470:55 | receiver for default_name |
|
||||
| main.rs:471:18:471:18 | n | file://:0:0:0:0 | &ref | main.rs:471:18:471:18 | receiver for n |
|
||||
| main.rs:494:13:494:13 | a | file://:0:0:0:0 | &ref | main.rs:494:13:494:13 | receiver for a |
|
||||
| main.rs:495:13:495:13 | b | file://:0:0:0:0 | &ref | main.rs:495:13:495:13 | receiver for b |
|
||||
| main.rs:496:18:496:18 | b | file://:0:0:0:0 | &ref | main.rs:496:18:496:18 | receiver for b |
|
||||
| main.rs:505:15:505:24 | source(...) | file://:0:0:0:0 | element | main.rs:505:14:505:34 | [...] |
|
||||
|
||||
@@ -73,6 +73,18 @@ multipleCallTargets
|
||||
| test.rs:977:14:977:29 | ...::_print(...) |
|
||||
| test.rs:979:27:979:36 | ...::_print(...) |
|
||||
| test.rs:980:28:980:41 | ...::_print(...) |
|
||||
| test_futures_io.rs:45:27:45:84 | ...::read(...) |
|
||||
| test_futures_io.rs:49:27:49:51 | reader.read(...) |
|
||||
| test_futures_io.rs:83:22:83:39 | reader2.fill_buf() |
|
||||
| test_futures_io.rs:103:27:103:85 | ...::read(...) |
|
||||
| test_futures_io.rs:107:27:107:52 | reader2.read(...) |
|
||||
| test_futures_io.rs:125:22:125:39 | reader2.fill_buf() |
|
||||
| test_futures_io.rs:132:27:132:62 | reader2.read_until(...) |
|
||||
| test_futures_io.rs:139:27:139:54 | reader2.read_line(...) |
|
||||
| test_futures_io.rs:146:27:146:58 | reader2.read_to_end(...) |
|
||||
| test_futures_io.rs:152:32:152:46 | reader2.lines() |
|
||||
| test_futures_io.rs:153:14:153:32 | lines_stream.next() |
|
||||
| test_futures_io.rs:154:32:154:50 | lines_stream.next() |
|
||||
| web_frameworks.rs:13:14:13:22 | a.as_str() |
|
||||
| web_frameworks.rs:13:14:13:23 | a.as_str() |
|
||||
| web_frameworks.rs:14:14:14:24 | a.as_bytes() |
|
||||
|
||||
@@ -309,28 +309,28 @@ async fn test_tokio_stdin() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = [0u8; 100];
|
||||
let _bytes = stdin.read(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
let _bytes = stdin.read_to_end(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_to_end` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = String::new();
|
||||
let _bytes = stdin.read_to_string(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_to_string` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = [0; 100];
|
||||
stdin.read_exact(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_exact` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
@@ -339,17 +339,17 @@ async fn test_tokio_stdin() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let v2 = stdin.read_i16().await?;
|
||||
let v3 = stdin.read_f32().await?;
|
||||
let v4 = stdin.read_i64_le().await?;
|
||||
sink(v1); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_u8` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v2); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_i16` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v3); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_f32` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v4); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_i64_le` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v1); // $ hasTaintFlow
|
||||
sink(v2); // $ hasTaintFlow
|
||||
sink(v3); // $ hasTaintFlow
|
||||
sink(v4); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = bytes::BytesMut::new();
|
||||
stdin.read_buf(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_buf` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
// --- async reading from stdin (BufReader) ---
|
||||
@@ -357,7 +357,7 @@ async fn test_tokio_stdin() -> Result<(), Box<dyn std::error::Error>> {
|
||||
{
|
||||
let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources]
|
||||
let data = reader.fill_buf().await?;
|
||||
sink(&data); // $ MISSING: hasTaintFlow -- we cannot resolve the `fill_buf` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(&data); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
@@ -370,31 +370,31 @@ async fn test_tokio_stdin() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut buffer = String::new();
|
||||
let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources]
|
||||
reader.read_line(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_line` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources]
|
||||
reader.read_until(b',', &mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_until` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(buffer[0]); // $ MISSING: hasTaintFlow -- we cannot resolve the `read_until` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow
|
||||
sink(buffer[0]); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
{
|
||||
let mut reader_split = tokio::io::BufReader::new(tokio::io::stdin()).split(b','); // $ Alert[rust/summary/taint-sources]
|
||||
sink(reader_split.next_segment().await?.unwrap()); // $ MISSING: hasTaintFlow -- we cannot resolve the `split` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(reader_split.next_segment().await?.unwrap()); // $ hasTaintFlow
|
||||
while let Some(chunk) = reader_split.next_segment().await? {
|
||||
sink(chunk); // $ MISSING: hasTaintFlow
|
||||
sink(chunk); // $ hasTaintFlow
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources]
|
||||
let mut lines = reader.lines();
|
||||
sink(lines.next_line().await?.unwrap()); // $ MISSING: hasTaintFlow -- we cannot resolve the `lines` call above, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(lines.next_line().await?.unwrap()); // $ hasTaintFlow
|
||||
while let Some(line) = lines.next_line().await? {
|
||||
sink(line); // $ MISSING: hasTaintFlow
|
||||
sink(line); // $ hasTaintFlow
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,25 +583,25 @@ async fn test_tokio_file() -> std::io::Result<()> {
|
||||
{
|
||||
let mut buffer = [0u8; 100];
|
||||
let _bytes = file.read(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
{
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
let _bytes = file.read_to_end(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_to_end` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
{
|
||||
let mut buffer = String::new();
|
||||
let _bytes = file.read_to_string(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_to_string` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
{
|
||||
let mut buffer = [0; 100];
|
||||
file.read_exact(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_exact` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
{
|
||||
@@ -609,16 +609,16 @@ async fn test_tokio_file() -> std::io::Result<()> {
|
||||
let v2 = file.read_i16().await?;
|
||||
let v3 = file.read_f32().await?;
|
||||
let v4 = file.read_i64_le().await?;
|
||||
sink(v1); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_u8` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v2); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_i16` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v3); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_f32` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v4); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_i64_le` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(v1); // $ hasTaintFlow="file.txt"
|
||||
sink(v2); // $ hasTaintFlow="file.txt"
|
||||
sink(v3); // $ hasTaintFlow="file.txt"
|
||||
sink(v4); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
{
|
||||
let mut buffer = bytes::BytesMut::new();
|
||||
file.read_buf(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `read_buf` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ hasTaintFlow="file.txt"
|
||||
}
|
||||
|
||||
// --- OpenOptions ---
|
||||
@@ -627,7 +627,7 @@ async fn test_tokio_file() -> std::io::Result<()> {
|
||||
let mut f1 = tokio::fs::OpenOptions::new().open("f1.txt").await?; // $ Alert[rust/summary/taint-sources]
|
||||
let mut buffer = [0u8; 1024];
|
||||
let _bytes = f1.read(&mut buffer).await?;
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow="f1.txt"
|
||||
sink(&buffer); // $ hasTaintFlow="f1.txt"
|
||||
}
|
||||
|
||||
// --- misc operations ---
|
||||
@@ -775,8 +775,8 @@ async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> {
|
||||
sink(buffer1[0]); // $ hasTaintFlow=address
|
||||
|
||||
println!("buffer2 = {:?}", buffer2);
|
||||
sink(&buffer2); // $ MISSING: hasTaintFlow=address -- we cannot resolve the `read` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(buffer2[0]); // $ MISSING: hasTaintFlow=address -- we cannot resolve the `read` call above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer2); // $ hasTaintFlow=address
|
||||
sink(buffer2[0]); // $ hasTaintFlow=address
|
||||
|
||||
let buffer_string = String::from_utf8_lossy(&buffer2[..n2]);
|
||||
println!("string = {}", buffer_string);
|
||||
|
||||
@@ -43,12 +43,12 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> {
|
||||
// using the `AsyncReadExt::read` extension method (higher-level)
|
||||
let mut buffer1 = [0u8; 64];
|
||||
let bytes_read1 = futures::io::AsyncReadExt::read(&mut reader, &mut buffer1).await?; // we cannot resolve the `read` call, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer1[..bytes_read1]); // $ MISSING: hasTaintFlow=url
|
||||
sink(&buffer1[..bytes_read1]); // $ hasTaintFlow=url
|
||||
|
||||
let mut buffer2 = [0u8; 64];
|
||||
let bytes_read2 = reader.read(&mut buffer2).await?; // we cannot resolve the `read` call, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
|
||||
sink(&buffer2[..bytes_read2]); // $ MISSING: hasTaintFlow=url
|
||||
sink(&buffer2[..bytes_read2]); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
let mut reader2 = futures::io::BufReader::new(reader);
|
||||
@@ -81,7 +81,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> {
|
||||
{
|
||||
// using the `AsyncBufReadExt::fill_buf` extension method (higher-level)
|
||||
let buffer = reader2.fill_buf().await?; // we cannot resolve the `fill_buf` call, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(buffer); // $ MISSING: hasTaintFlow=url
|
||||
sink(buffer); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
@@ -101,11 +101,11 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> {
|
||||
// using the `AsyncReadExt::read` extension method (higher-level)
|
||||
let mut buffer1 = [0u8; 64];
|
||||
let bytes_read1 = futures::io::AsyncReadExt::read(&mut reader2, &mut buffer1).await?; // we cannot resolve the `read` call, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer1[..bytes_read1]); // $ MISSING: hasTaintFlow=url
|
||||
sink(&buffer1[..bytes_read1]); // $ hasTaintFlow=url
|
||||
|
||||
let mut buffer2 = [0u8; 64];
|
||||
let bytes_read2 = reader2.read(&mut buffer2).await?; // we cannot resolve the `read` call, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer2[..bytes_read2]); // $ MISSING: hasTaintFlow=url
|
||||
sink(&buffer2[..bytes_read2]); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
@@ -123,28 +123,28 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> {
|
||||
{
|
||||
// using the `AsyncBufReadExt::fill_buf` extension method (higher-level)
|
||||
let buffer = reader2.fill_buf().await?; // we cannot resolve the `fill_buf` call, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(buffer); // $ MISSING: hasTaintFlow=url
|
||||
sink(buffer); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
// using the `AsyncBufReadExt::read_until` extension method
|
||||
let mut line = Vec::new();
|
||||
let _bytes_read = reader2.read_until(b'\n', &mut line).await?; // we cannot resolve the `read_until` call, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(&line); // $ MISSING: hasTaintFlow=url
|
||||
sink(&line); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
// using the `AsyncBufReadExt::read_line` extension method
|
||||
let mut line = String::new();
|
||||
let _bytes_read = reader2.read_line(&mut line).await?; // we cannot resolve the `read_line` call, which comes from `impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}` in `async_buf_read_ext.rs`
|
||||
sink(&line); // $ MISSING: hasTaintFlow=url
|
||||
sink(&line); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
// using the `AsyncBufReadExt::read_to_end` extension method
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
let _bytes_read = reader2.read_to_end(&mut buffer).await?; // we cannot resolve the `read` call, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
|
||||
sink(&buffer); // $ MISSING: hasTaintFlow=url
|
||||
sink(&buffer); // $ hasTaintFlow=url
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ fn int_div(
|
||||
) -> Result<i32> // $ item=my::Result $ item=i32
|
||||
{
|
||||
if y == 0 {
|
||||
return Err("Div by zero".to_string()); // $ item=Err
|
||||
return Err("Div by zero".to_string()); // $ item=Err item=to_string
|
||||
}
|
||||
Ok(x / y) // $ item=Ok
|
||||
}
|
||||
|
||||
161
rust/ql/test/library-tests/type-inference/blanket_impl.rs
Normal file
161
rust/ql/test/library-tests/type-inference/blanket_impl.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
// Tests for method resolution targeting blanket trait implementations
|
||||
|
||||
mod basic_blanket_impl {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct S1;
|
||||
|
||||
trait Clone1 {
|
||||
fn clone1(&self) -> Self;
|
||||
}
|
||||
|
||||
trait Duplicatable {
|
||||
fn duplicate(&self) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl Clone1 for S1 {
|
||||
// S1::clone1
|
||||
fn clone1(&self) -> Self {
|
||||
*self // $ target=deref
|
||||
}
|
||||
}
|
||||
|
||||
// Blanket implementation for all types that implement Display and Clone
|
||||
impl<T: Clone1> Duplicatable for T {
|
||||
// Clone1duplicate
|
||||
fn duplicate(&self) -> Self {
|
||||
self.clone1() // $ target=clone1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_basic_blanket() {
|
||||
let x = S1.clone1(); // $ target=S1::clone1
|
||||
println!("{x:?}");
|
||||
let y = S1.duplicate(); // $ target=Clone1duplicate
|
||||
println!("{y:?}");
|
||||
}
|
||||
}
|
||||
|
||||
mod extension_trait_blanket_impl {
|
||||
// This tests:
|
||||
// 1. A trait that is implemented for a type parameter
|
||||
// 2. An extension trait
|
||||
// 3. A blanket implementation of the extension trait for a type parameter
|
||||
|
||||
trait Flag {
|
||||
fn read_flag(&self) -> bool;
|
||||
}
|
||||
|
||||
trait TryFlag {
|
||||
fn try_read_flag(&self) -> Option<bool>;
|
||||
}
|
||||
|
||||
impl<Fl> TryFlag for Fl
|
||||
where
|
||||
Fl: Flag,
|
||||
{
|
||||
fn try_read_flag(&self) -> Option<bool> {
|
||||
Some(self.read_flag()) // $ target=read_flag
|
||||
}
|
||||
}
|
||||
|
||||
trait TryFlagExt: TryFlag {
|
||||
// TryFlagExt::try_read_flag_twice
|
||||
fn try_read_flag_twice(&self) -> Option<bool> {
|
||||
self.try_read_flag() // $ target=try_read_flag
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TryFlag> TryFlagExt for T {}
|
||||
|
||||
trait AnotherTryFlag {
|
||||
// AnotherTryFlag::try_read_flag_twice
|
||||
fn try_read_flag_twice(&self) -> Option<bool>;
|
||||
}
|
||||
|
||||
struct MyTryFlag {
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl TryFlag for MyTryFlag {
|
||||
// MyTryFlag::try_read_flag
|
||||
fn try_read_flag(&self) -> Option<bool> {
|
||||
Some(self.flag) // $ fieldof=MyTryFlag
|
||||
}
|
||||
}
|
||||
|
||||
struct MyFlag {
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl Flag for MyFlag {
|
||||
// MyFlag::read_flag
|
||||
fn read_flag(&self) -> bool {
|
||||
self.flag // $ fieldof=MyFlag
|
||||
}
|
||||
}
|
||||
|
||||
struct MyOtherFlag {
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl AnotherTryFlag for MyOtherFlag {
|
||||
// MyOtherFlag::try_read_flag_twice
|
||||
fn try_read_flag_twice(&self) -> Option<bool> {
|
||||
Some(self.flag) // $ fieldof=MyOtherFlag
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let my_try_flag = MyTryFlag { flag: true };
|
||||
let result = my_try_flag.try_read_flag_twice(); // $ target=TryFlagExt::try_read_flag_twice
|
||||
|
||||
let my_flag = MyFlag { flag: true };
|
||||
// Here `TryFlagExt::try_read_flag_twice` is a target since there is a
|
||||
// blanket implementaton of `TryFlag` for `Flag`.
|
||||
let result = my_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
|
||||
|
||||
let my_other_flag = MyOtherFlag { flag: true };
|
||||
// Here `TryFlagExt::try_read_flag_twice` is _not_ a target since
|
||||
// `MyOtherFlag` does not implement `TryFlag`.
|
||||
let result = my_other_flag.try_read_flag_twice(); // $ target=MyOtherFlag::try_read_flag_twice
|
||||
}
|
||||
}
|
||||
|
||||
pub mod sql_exec {
|
||||
// a highly simplified model of `MySqlConnection.execute` in SQLx
|
||||
|
||||
trait Connection {}
|
||||
|
||||
trait Executor {
|
||||
fn execute1(&self);
|
||||
fn execute2<E>(&self, query: E);
|
||||
}
|
||||
|
||||
impl<T: Connection> Executor for T {
|
||||
fn execute1(&self) {
|
||||
println!("Executor::execute1");
|
||||
}
|
||||
|
||||
fn execute2<E>(&self, _query: E) {
|
||||
println!("Executor::execute2");
|
||||
}
|
||||
}
|
||||
|
||||
struct MySqlConnection {}
|
||||
|
||||
impl Connection for MySqlConnection {}
|
||||
|
||||
pub fn f() {
|
||||
let c = MySqlConnection {}; // $ certainType=c:MySqlConnection
|
||||
|
||||
c.execute1(); // $ target=execute1
|
||||
MySqlConnection::execute1(&c); // $ MISSING: target=execute1
|
||||
|
||||
c.execute2("SELECT * FROM users"); // $ target=execute2
|
||||
c.execute2::<&str>("SELECT * FROM users"); // $ target=execute2
|
||||
MySqlConnection::execute2(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
MySqlConnection::execute2::<&str>(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ fn test_assoc_type(obj: &dyn AssocTrait<i64, AP = bool>) {
|
||||
pub fn test() {
|
||||
test_basic_dyn_trait(&MyStruct { value: 42 }); // $ target=test_basic_dyn_trait
|
||||
test_generic_dyn_trait(&GenStruct {
|
||||
value: "".to_string(),
|
||||
value: "".to_string(), // $ target=to_string
|
||||
}); // $ target=test_generic_dyn_trait
|
||||
test_poly_dyn_trait(); // $ target=test_poly_dyn_trait
|
||||
test_assoc_type(&GenStruct { value: 100 }); // $ target=test_assoc_type
|
||||
|
||||
@@ -365,7 +365,7 @@ mod method_non_parametric_trait_impl {
|
||||
|
||||
fn type_bound_type_parameter_impl<TP: MyTrait<S1>>(thing: TP) -> S1 {
|
||||
// The trait bound on `TP` makes the implementation of `ConvertTo` valid
|
||||
thing.convert_to() // $ MISSING: target=T::convert_to
|
||||
thing.convert_to() // $ target=T::convert_to
|
||||
}
|
||||
|
||||
pub fn f() {
|
||||
@@ -437,7 +437,7 @@ mod method_non_parametric_trait_impl {
|
||||
let x = get_snd_fst(c); // $ type=x:S1 target=get_snd_fst
|
||||
|
||||
let thing = MyThing { a: S1 };
|
||||
let i = thing.convert_to(); // $ MISSING: type=i:S1 target=T::convert_to
|
||||
let i = thing.convert_to(); // $ type=i:S1 target=T::convert_to
|
||||
let j = convert_to(thing); // $ type=j:S1 target=convert_to
|
||||
}
|
||||
}
|
||||
@@ -1376,7 +1376,7 @@ mod method_call_type_conversion {
|
||||
let t = x7.m1(); // $ target=m1 type=t:& type=t:&T.S2
|
||||
println!("{:?}", x7);
|
||||
|
||||
let x9: String = "Hello".to_string(); // $ certainType=x9:String
|
||||
let x9: String = "Hello".to_string(); // $ certainType=x9:String target=to_string
|
||||
|
||||
// Implicit `String` -> `str` conversion happens via the `Deref` trait:
|
||||
// https://doc.rust-lang.org/std/string/struct.String.html#deref.
|
||||
@@ -2569,43 +2569,6 @@ pub mod pattern_matching_experimental {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod exec {
|
||||
// a highly simplified model of `MySqlConnection.execute` in SQLx
|
||||
|
||||
trait Connection {}
|
||||
|
||||
trait Executor {
|
||||
fn execute1(&self);
|
||||
fn execute2<E>(&self, query: E);
|
||||
}
|
||||
|
||||
impl<T: Connection> Executor for T {
|
||||
fn execute1(&self) {
|
||||
println!("Executor::execute1");
|
||||
}
|
||||
|
||||
fn execute2<E>(&self, _query: E) {
|
||||
println!("Executor::execute2");
|
||||
}
|
||||
}
|
||||
|
||||
struct MySqlConnection {}
|
||||
|
||||
impl Connection for MySqlConnection {}
|
||||
|
||||
pub fn f() {
|
||||
let c = MySqlConnection {}; // $ certainType=c:MySqlConnection
|
||||
|
||||
c.execute1(); // $ MISSING: target=execute1
|
||||
MySqlConnection::execute1(&c); // $ MISSING: target=execute1
|
||||
|
||||
c.execute2("SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
c.execute2::<&str>("SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
MySqlConnection::execute2(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
MySqlConnection::execute2::<&str>(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
|
||||
}
|
||||
}
|
||||
|
||||
pub mod path_buf {
|
||||
// a highly simplified model of `PathBuf::canonicalize`
|
||||
|
||||
@@ -2655,6 +2618,7 @@ pub mod path_buf {
|
||||
mod closure;
|
||||
mod dereference;
|
||||
mod dyn_type;
|
||||
mod blanket_impl;
|
||||
|
||||
fn main() {
|
||||
field_access::f(); // $ target=f
|
||||
@@ -2683,7 +2647,6 @@ fn main() {
|
||||
macros::f(); // $ target=f
|
||||
method_determined_by_argument_type::f(); // $ target=f
|
||||
tuples::f(); // $ target=f
|
||||
exec::f(); // $ target=f
|
||||
path_buf::f(); // $ target=f
|
||||
dereference::test(); // $ target=test
|
||||
pattern_matching::test_all_patterns(); // $ target=test_all_patterns
|
||||
|
||||
@@ -1,4 +1,143 @@
|
||||
inferType
|
||||
| blanket_impl.rs:8:19:8:23 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:8:19:8:23 | SelfParam | &T | blanket_impl.rs:7:5:9:5 | Self [trait Clone1] |
|
||||
| blanket_impl.rs:12:22:12:26 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:12:22:12:26 | SelfParam | &T | blanket_impl.rs:11:5:15:5 | Self [trait Duplicatable] |
|
||||
| blanket_impl.rs:19:19:19:23 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:19:19:19:23 | SelfParam | &T | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:19:34:21:9 | { ... } | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:20:13:20:17 | * ... | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:20:14:20:17 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:20:14:20:17 | self | &T | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:27:22:27:26 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:27:22:27:26 | SelfParam | &T | blanket_impl.rs:25:10:25:18 | T |
|
||||
| blanket_impl.rs:27:37:29:9 | { ... } | | blanket_impl.rs:25:10:25:18 | T |
|
||||
| blanket_impl.rs:28:13:28:16 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:28:13:28:16 | self | &T | blanket_impl.rs:25:10:25:18 | T |
|
||||
| blanket_impl.rs:28:13:28:25 | self.clone1() | | blanket_impl.rs:25:10:25:18 | T |
|
||||
| blanket_impl.rs:33:13:33:13 | x | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:33:17:33:18 | S1 | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:33:17:33:27 | S1.clone1() | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:34:18:34:24 | "{x:?}\\n" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:34:18:34:24 | "{x:?}\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:34:18:34:24 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:34:18:34:24 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:34:20:34:20 | x | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:35:13:35:13 | y | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:35:17:35:18 | S1 | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:35:17:35:30 | S1.duplicate() | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:36:18:36:24 | "{y:?}\\n" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:36:18:36:24 | "{y:?}\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:36:18:36:24 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:36:18:36:24 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:36:20:36:20 | y | | blanket_impl.rs:4:5:5:14 | S1 |
|
||||
| blanket_impl.rs:47:22:47:26 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:47:22:47:26 | SelfParam | &T | blanket_impl.rs:46:5:48:5 | Self [trait Flag] |
|
||||
| blanket_impl.rs:51:26:51:30 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:51:26:51:30 | SelfParam | &T | blanket_impl.rs:50:5:52:5 | Self [trait TryFlag] |
|
||||
| blanket_impl.rs:58:26:58:30 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:58:26:58:30 | SelfParam | &T | blanket_impl.rs:54:10:54:11 | Fl |
|
||||
| blanket_impl.rs:58:49:60:9 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:58:49:60:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:59:13:59:34 | Some(...) | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:59:13:59:34 | Some(...) | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:59:18:59:21 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:59:18:59:21 | self | &T | blanket_impl.rs:54:10:54:11 | Fl |
|
||||
| blanket_impl.rs:59:18:59:33 | self.read_flag() | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:65:32:65:36 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:65:32:65:36 | SelfParam | &T | blanket_impl.rs:63:5:68:5 | Self [trait TryFlagExt] |
|
||||
| blanket_impl.rs:65:55:67:9 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:65:55:67:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:66:13:66:16 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:66:13:66:16 | self | &T | blanket_impl.rs:63:5:68:5 | Self [trait TryFlagExt] |
|
||||
| blanket_impl.rs:66:13:66:32 | self.try_read_flag() | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:66:13:66:32 | self.try_read_flag() | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:74:32:74:36 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:74:32:74:36 | SelfParam | &T | blanket_impl.rs:72:5:75:5 | Self [trait AnotherTryFlag] |
|
||||
| blanket_impl.rs:83:26:83:30 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:83:26:83:30 | SelfParam | &T | blanket_impl.rs:77:5:79:5 | MyTryFlag |
|
||||
| blanket_impl.rs:83:49:85:9 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:83:49:85:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:84:13:84:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:84:13:84:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:84:18:84:21 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:84:18:84:21 | self | &T | blanket_impl.rs:77:5:79:5 | MyTryFlag |
|
||||
| blanket_impl.rs:84:18:84:26 | self.flag | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:94:22:94:26 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:94:22:94:26 | SelfParam | &T | blanket_impl.rs:88:5:90:5 | MyFlag |
|
||||
| blanket_impl.rs:94:37:96:9 | { ... } | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:95:13:95:16 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:95:13:95:16 | self | &T | blanket_impl.rs:88:5:90:5 | MyFlag |
|
||||
| blanket_impl.rs:95:13:95:21 | self.flag | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:105:32:105:36 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:105:32:105:36 | SelfParam | &T | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
|
||||
| blanket_impl.rs:105:55:107:9 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:105:55:107:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:106:13:106:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:106:13:106:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:106:18:106:21 | self | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:106:18:106:21 | self | &T | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
|
||||
| blanket_impl.rs:106:18:106:26 | self.flag | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:111:13:111:23 | my_try_flag | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
|
||||
| blanket_impl.rs:111:27:111:50 | MyTryFlag {...} | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
|
||||
| blanket_impl.rs:111:45:111:48 | true | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:112:13:112:18 | result | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:112:13:112:18 | result | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:112:22:112:32 | my_try_flag | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
|
||||
| blanket_impl.rs:112:22:112:54 | my_try_flag.try_read_flag_twice() | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:112:22:112:54 | my_try_flag.try_read_flag_twice() | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:114:13:114:19 | my_flag | | blanket_impl.rs:88:5:90:5 | MyFlag |
|
||||
| blanket_impl.rs:114:23:114:43 | MyFlag {...} | | blanket_impl.rs:88:5:90:5 | MyFlag |
|
||||
| blanket_impl.rs:114:38:114:41 | true | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:117:22:117:28 | my_flag | | blanket_impl.rs:88:5:90:5 | MyFlag |
|
||||
| blanket_impl.rs:119:13:119:25 | my_other_flag | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
|
||||
| blanket_impl.rs:119:29:119:54 | MyOtherFlag {...} | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
|
||||
| blanket_impl.rs:119:49:119:52 | true | | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:122:13:122:18 | result | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:122:13:122:18 | result | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:122:22:122:34 | my_other_flag | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
|
||||
| blanket_impl.rs:122:22:122:56 | my_other_flag.try_read_flag_twice() | | {EXTERNAL LOCATION} | Option |
|
||||
| blanket_impl.rs:122:22:122:56 | my_other_flag.try_read_flag_twice() | T | {EXTERNAL LOCATION} | bool |
|
||||
| blanket_impl.rs:132:21:132:25 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:132:21:132:25 | SelfParam | &T | blanket_impl.rs:131:5:134:5 | Self [trait Executor] |
|
||||
| blanket_impl.rs:133:24:133:28 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:133:24:133:28 | SelfParam | &T | blanket_impl.rs:131:5:134:5 | Self [trait Executor] |
|
||||
| blanket_impl.rs:133:31:133:35 | query | | blanket_impl.rs:133:21:133:21 | E |
|
||||
| blanket_impl.rs:137:21:137:25 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:137:21:137:25 | SelfParam | &T | blanket_impl.rs:136:10:136:22 | T |
|
||||
| blanket_impl.rs:138:22:138:41 | "Executor::execute1\\n" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:138:22:138:41 | "Executor::execute1\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:138:22:138:41 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:138:22:138:41 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:141:24:141:28 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:141:24:141:28 | SelfParam | &T | blanket_impl.rs:136:10:136:22 | T |
|
||||
| blanket_impl.rs:141:31:141:36 | _query | | blanket_impl.rs:141:21:141:21 | E |
|
||||
| blanket_impl.rs:142:22:142:41 | "Executor::execute2\\n" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:142:22:142:41 | "Executor::execute2\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:142:22:142:41 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:142:22:142:41 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| blanket_impl.rs:151:13:151:13 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:151:17:151:34 | MySqlConnection {...} | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:153:9:153:9 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:154:35:154:36 | &c | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:154:35:154:36 | &c | &T | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:154:36:154:36 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:156:9:156:9 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:156:20:156:40 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:156:20:156:40 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:157:9:157:9 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:157:28:157:48 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:157:28:157:48 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:158:35:158:36 | &c | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:158:35:158:36 | &c | &T | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:158:36:158:36 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:158:39:158:59 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:158:39:158:59 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| blanket_impl.rs:159:43:159:44 | &c | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:159:43:159:44 | &c | &T | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:159:44:159:44 | c | | blanket_impl.rs:146:5:146:29 | MySqlConnection |
|
||||
| blanket_impl.rs:159:47:159:67 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| blanket_impl.rs:159:47:159:67 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| closure.rs:6:13:6:22 | my_closure | | {EXTERNAL LOCATION} | dyn FnOnce |
|
||||
| closure.rs:6:13:6:22 | my_closure | dyn(Args) | file://:0:0:0:0 | (T_2) |
|
||||
| closure.rs:6:13:6:22 | my_closure | dyn(Args).0(2) | {EXTERNAL LOCATION} | bool |
|
||||
@@ -624,10 +763,13 @@ inferType
|
||||
| dyn_type.rs:103:28:105:5 | &... | | file://:0:0:0:0 | & |
|
||||
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:10:1:13:1 | dyn GenericGet |
|
||||
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct |
|
||||
| dyn_type.rs:103:28:105:5 | &... | &T.A | {EXTERNAL LOCATION} | String |
|
||||
| dyn_type.rs:103:28:105:5 | &... | &T.dyn(A) | {EXTERNAL LOCATION} | String |
|
||||
| dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
|
||||
| dyn_type.rs:103:29:105:5 | GenStruct {...} | A | {EXTERNAL LOCATION} | String |
|
||||
| dyn_type.rs:104:16:104:17 | "" | | file://:0:0:0:0 | & |
|
||||
| dyn_type.rs:104:16:104:17 | "" | &T | {EXTERNAL LOCATION} | str |
|
||||
| dyn_type.rs:104:16:104:29 | "".to_string() | | {EXTERNAL LOCATION} | String |
|
||||
| dyn_type.rs:107:21:107:45 | &... | | file://:0:0:0:0 | & |
|
||||
| dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
|
||||
| dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct |
|
||||
@@ -1260,8 +1402,10 @@ inferType
|
||||
| main.rs:439:21:439:37 | MyThing {...} | | main.rs:224:5:227:5 | MyThing |
|
||||
| main.rs:439:21:439:37 | MyThing {...} | A | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:439:34:439:35 | S1 | | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:440:13:440:13 | i | | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:440:17:440:21 | thing | | main.rs:224:5:227:5 | MyThing |
|
||||
| main.rs:440:17:440:21 | thing | A | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:440:17:440:34 | thing.convert_to() | | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:441:13:441:13 | j | | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:441:17:441:33 | convert_to(...) | | main.rs:235:5:236:14 | S1 |
|
||||
| main.rs:441:28:441:32 | thing | | main.rs:224:5:227:5 | MyThing |
|
||||
@@ -3187,14 +3331,22 @@ inferType
|
||||
| main.rs:1706:13:1709:13 | Vec2 {...} | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1707:20:1707:23 | self | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1707:20:1707:25 | self.x | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1707:20:1707:33 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1707:20:1707:33 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1707:20:1707:33 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1707:29:1707:31 | rhs | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1707:29:1707:33 | rhs.x | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1707:29:1707:33 | rhs.x | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1707:29:1707:33 | rhs.x | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1708:20:1708:23 | self | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1708:20:1708:25 | self.y | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1708:20:1708:33 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1708:20:1708:33 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1708:20:1708:33 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1708:29:1708:31 | rhs | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1708:29:1708:33 | rhs.y | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1708:29:1708:33 | rhs.y | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1708:29:1708:33 | rhs.y | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1714:25:1714:33 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:1714:25:1714:33 | SelfParam | &T | main.rs:1586:5:1591:5 | Vec2 |
|
||||
| main.rs:1714:36:1714:38 | rhs | | main.rs:1586:5:1591:5 | Vec2 |
|
||||
@@ -3532,9 +3684,13 @@ inferType
|
||||
| main.rs:1857:26:1857:30 | 33i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1857:26:1857:38 | ... & ... | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1857:34:1857:38 | 34i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:13:1858:21 | i64_bitor | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1858:13:1858:21 | i64_bitor | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:13:1858:21 | i64_bitor | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:25:1858:29 | 35i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:25:1858:37 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
|
||||
| main.rs:1858:25:1858:37 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:25:1858:37 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1858:33:1858:37 | 36i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1859:13:1859:22 | i64_bitxor | | {EXTERNAL LOCATION} | i64 |
|
||||
| main.rs:1859:26:1859:30 | 37i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
@@ -4922,89 +5078,49 @@ inferType
|
||||
| main.rs:2566:26:2566:43 | "Nested boxed: {}\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2566:26:2566:59 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2566:26:2566:59 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2578:21:2578:25 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2578:21:2578:25 | SelfParam | &T | main.rs:2577:5:2580:5 | Self [trait Executor] |
|
||||
| main.rs:2579:24:2579:28 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2579:24:2579:28 | SelfParam | &T | main.rs:2577:5:2580:5 | Self [trait Executor] |
|
||||
| main.rs:2579:31:2579:35 | query | | main.rs:2579:21:2579:21 | E |
|
||||
| main.rs:2583:21:2583:25 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2583:21:2583:25 | SelfParam | &T | main.rs:2582:10:2582:22 | T |
|
||||
| main.rs:2584:22:2584:41 | "Executor::execute1\\n" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2584:22:2584:41 | "Executor::execute1\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2584:22:2584:41 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2584:22:2584:41 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2587:24:2587:28 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2587:24:2587:28 | SelfParam | &T | main.rs:2582:10:2582:22 | T |
|
||||
| main.rs:2587:31:2587:36 | _query | | main.rs:2587:21:2587:21 | E |
|
||||
| main.rs:2588:22:2588:41 | "Executor::execute2\\n" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2588:22:2588:41 | "Executor::execute2\\n" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2588:22:2588:41 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2588:22:2588:41 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
|
||||
| main.rs:2597:13:2597:13 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2597:17:2597:34 | MySqlConnection {...} | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2599:9:2599:9 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2600:35:2600:36 | &c | | file://:0:0:0:0 | & |
|
||||
| main.rs:2600:35:2600:36 | &c | &T | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2600:36:2600:36 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2602:9:2602:9 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2602:20:2602:40 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2602:20:2602:40 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2603:9:2603:9 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2603:28:2603:48 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2603:28:2603:48 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2604:35:2604:36 | &c | | file://:0:0:0:0 | & |
|
||||
| main.rs:2604:35:2604:36 | &c | &T | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2604:36:2604:36 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2604:39:2604:59 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2604:39:2604:59 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2605:43:2605:44 | &c | | file://:0:0:0:0 | & |
|
||||
| main.rs:2605:43:2605:44 | &c | &T | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2605:44:2605:44 | c | | main.rs:2592:5:2592:29 | MySqlConnection |
|
||||
| main.rs:2605:47:2605:67 | "SELECT * FROM users" | | file://:0:0:0:0 | & |
|
||||
| main.rs:2605:47:2605:67 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str |
|
||||
| main.rs:2615:36:2617:9 | { ... } | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2616:13:2616:19 | Path {...} | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2619:29:2619:33 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2619:29:2619:33 | SelfParam | &T | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2619:59:2621:9 | { ... } | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2619:59:2621:9 | { ... } | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2619:59:2621:9 | { ... } | T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2620:13:2620:30 | Ok(...) | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2620:13:2620:30 | Ok(...) | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2620:13:2620:30 | Ok(...) | T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2620:16:2620:29 | ...::new(...) | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2627:39:2629:9 | { ... } | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2628:13:2628:22 | PathBuf {...} | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2637:18:2637:22 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2637:18:2637:22 | SelfParam | &T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2637:34:2641:9 | { ... } | | file://:0:0:0:0 | & |
|
||||
| main.rs:2637:34:2641:9 | { ... } | &T | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2639:33:2639:43 | ...::new(...) | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2640:13:2640:17 | &path | | file://:0:0:0:0 | & |
|
||||
| main.rs:2640:13:2640:17 | &path | &T | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2640:14:2640:17 | path | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2645:13:2645:17 | path1 | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2645:21:2645:31 | ...::new(...) | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2646:13:2646:17 | path2 | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2646:13:2646:17 | path2 | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2646:13:2646:17 | path2 | T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2646:21:2646:25 | path1 | | main.rs:2612:5:2612:22 | Path |
|
||||
| main.rs:2646:21:2646:40 | path1.canonicalize() | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2646:21:2646:40 | path1.canonicalize() | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2646:21:2646:40 | path1.canonicalize() | T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2647:13:2647:17 | path3 | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2647:21:2647:25 | path2 | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2647:21:2647:25 | path2 | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2647:21:2647:25 | path2 | T | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2647:21:2647:34 | path2.unwrap() | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2649:13:2649:20 | pathbuf1 | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2649:24:2649:37 | ...::new(...) | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2650:24:2650:31 | pathbuf1 | | main.rs:2624:5:2624:25 | PathBuf |
|
||||
| main.rs:2661:5:2661:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2662:5:2662:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2662:20:2662:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2662:41:2662:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2678:5:2678:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
|
||||
| main.rs:2578:36:2580:9 | { ... } | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2579:13:2579:19 | Path {...} | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2582:29:2582:33 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2582:29:2582:33 | SelfParam | &T | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2582:59:2584:9 | { ... } | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2582:59:2584:9 | { ... } | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2582:59:2584:9 | { ... } | T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2583:13:2583:30 | Ok(...) | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2583:13:2583:30 | Ok(...) | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2583:13:2583:30 | Ok(...) | T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2583:16:2583:29 | ...::new(...) | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2590:39:2592:9 | { ... } | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2591:13:2591:22 | PathBuf {...} | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2600:18:2600:22 | SelfParam | | file://:0:0:0:0 | & |
|
||||
| main.rs:2600:18:2600:22 | SelfParam | &T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2600:34:2604:9 | { ... } | | file://:0:0:0:0 | & |
|
||||
| main.rs:2600:34:2604:9 | { ... } | &T | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2602:33:2602:43 | ...::new(...) | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2603:13:2603:17 | &path | | file://:0:0:0:0 | & |
|
||||
| main.rs:2603:13:2603:17 | &path | &T | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2603:14:2603:17 | path | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2608:13:2608:17 | path1 | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2608:21:2608:31 | ...::new(...) | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2609:13:2609:17 | path2 | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2609:13:2609:17 | path2 | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2609:13:2609:17 | path2 | T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2609:21:2609:25 | path1 | | main.rs:2575:5:2575:22 | Path |
|
||||
| main.rs:2609:21:2609:40 | path1.canonicalize() | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2609:21:2609:40 | path1.canonicalize() | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2609:21:2609:40 | path1.canonicalize() | T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2610:13:2610:17 | path3 | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2610:21:2610:25 | path2 | | {EXTERNAL LOCATION} | Result |
|
||||
| main.rs:2610:21:2610:25 | path2 | E | file://:0:0:0:0 | () |
|
||||
| main.rs:2610:21:2610:25 | path2 | T | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2610:21:2610:34 | path2.unwrap() | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2612:13:2612:20 | pathbuf1 | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2612:24:2612:37 | ...::new(...) | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2613:24:2613:31 | pathbuf1 | | main.rs:2587:5:2587:25 | PathBuf |
|
||||
| main.rs:2625:5:2625:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2626:5:2626:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2626:20:2626:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2626:41:2626:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
|
||||
| main.rs:2642:5:2642:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () |
|
||||
| pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option |
|
||||
|
||||
@@ -12,12 +12,14 @@ multipleCallTargets
|
||||
| sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() |
|
||||
| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() |
|
||||
| sqlx.rs:70:30:70:52 | unsafe_query_3.as_str() |
|
||||
| sqlx.rs:71:30:71:52 | unsafe_query_4.as_str() |
|
||||
| sqlx.rs:75:25:75:45 | safe_query_1.as_str() |
|
||||
| sqlx.rs:76:25:76:45 | safe_query_2.as_str() |
|
||||
| sqlx.rs:77:25:77:45 | safe_query_3.as_str() |
|
||||
| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() |
|
||||
| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() |
|
||||
| sqlx.rs:81:29:81:51 | unsafe_query_3.as_str() |
|
||||
| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() |
|
||||
| sqlx.rs:84:25:84:49 | prepared_query_1.as_str() |
|
||||
| sqlx.rs:85:25:85:49 | prepared_query_1.as_str() |
|
||||
| sqlx.rs:87:29:87:53 | prepared_query_1.as_str() |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
| sqlx.rs:77:13:77:23 | ...::query | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:77:13:77:23 | ...::query | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value |
|
||||
| sqlx.rs:78:13:78:23 | ...::query | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:78:13:78:23 | ...::query | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value |
|
||||
| sqlx.rs:80:17:80:27 | ...::query | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:80:17:80:27 | ...::query | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value |
|
||||
| sqlx.rs:82:17:82:27 | ...::query | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:82:17:82:27 | ...::query | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value |
|
||||
edges
|
||||
| sqlx.rs:47:9:47:18 | arg_string | sqlx.rs:53:27:53:36 | arg_string | provenance | |
|
||||
| sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:47:22:47:37 | ...::args(...) [element] | provenance | Src:MaD:3 |
|
||||
@@ -11,6 +12,7 @@ edges
|
||||
| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse() [Ok] | provenance | MaD:10 |
|
||||
| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse() [Ok] | provenance | MaD:10 |
|
||||
| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:54:27:54:39 | remote_string | provenance | |
|
||||
| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:59:17:59:72 | MacroExpr | provenance | |
|
||||
| sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | provenance | Src:MaD:2 |
|
||||
| sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | sqlx.rs:48:25:48:78 | ... .unwrap() | provenance | MaD:7 |
|
||||
| sqlx.rs:48:25:48:78 | ... .unwrap() | sqlx.rs:48:25:48:85 | ... .text() [Ok] | provenance | MaD:11 |
|
||||
@@ -38,6 +40,15 @@ edges
|
||||
| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() [&ref] | provenance | MaD:9 |
|
||||
| sqlx.rs:54:26:54:39 | &remote_string [&ref] | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | provenance | |
|
||||
| sqlx.rs:54:27:54:39 | remote_string | sqlx.rs:54:26:54:39 | &remote_string [&ref] | provenance | |
|
||||
| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:82:29:82:42 | unsafe_query_4 | provenance | |
|
||||
| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | provenance | MaD:9 |
|
||||
| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | provenance | MaD:5 |
|
||||
| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | provenance | MaD:9 |
|
||||
| sqlx.rs:59:9:59:15 | res | sqlx.rs:59:17:59:72 | { ... } | provenance | |
|
||||
| sqlx.rs:59:17:59:72 | ...::format(...) | sqlx.rs:59:9:59:15 | res | provenance | |
|
||||
| sqlx.rs:59:17:59:72 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | |
|
||||
| sqlx.rs:59:17:59:72 | MacroExpr | sqlx.rs:59:17:59:72 | ...::format(...) | provenance | MaD:12 |
|
||||
| sqlx.rs:59:17:59:72 | { ... } | sqlx.rs:59:17:59:72 | ...::must_use(...) | provenance | MaD:13 |
|
||||
| sqlx.rs:77:25:77:36 | safe_query_3 | sqlx.rs:77:25:77:45 | safe_query_3.as_str() [&ref] | provenance | MaD:9 |
|
||||
| sqlx.rs:77:25:77:36 | safe_query_3 | sqlx.rs:77:25:77:45 | safe_query_3.as_str() [&ref] | provenance | MaD:5 |
|
||||
| sqlx.rs:77:25:77:36 | safe_query_3 | sqlx.rs:77:25:77:45 | safe_query_3.as_str() [&ref] | provenance | MaD:9 |
|
||||
@@ -45,6 +56,11 @@ edges
|
||||
| sqlx.rs:77:25:77:45 | safe_query_3.as_str() [&ref] | sqlx.rs:77:13:77:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() [&ref] | sqlx.rs:78:13:78:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() [&ref] | sqlx.rs:80:17:80:27 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| sqlx.rs:82:29:82:42 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() [&ref] | provenance | MaD:9 |
|
||||
| sqlx.rs:82:29:82:42 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() [&ref] | provenance | MaD:5 |
|
||||
| sqlx.rs:82:29:82:42 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() [&ref] | provenance | MaD:9 |
|
||||
| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | sqlx.rs:82:17:82:27 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() [&ref] | sqlx.rs:82:17:82:27 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: sqlx_core::query::query; Argument[0]; sql-injection |
|
||||
| 2 | Source: reqwest::blocking::get; ReturnValue.Field[core::result::Result::Ok(0)]; remote |
|
||||
@@ -86,6 +102,12 @@ nodes
|
||||
| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | semmle.label | unsafe_query_2 [&ref] |
|
||||
| sqlx.rs:54:26:54:39 | &remote_string [&ref] | semmle.label | &remote_string [&ref] |
|
||||
| sqlx.rs:54:27:54:39 | remote_string | semmle.label | remote_string |
|
||||
| sqlx.rs:56:9:56:22 | unsafe_query_4 | semmle.label | unsafe_query_4 |
|
||||
| sqlx.rs:59:9:59:15 | res | semmle.label | res |
|
||||
| sqlx.rs:59:17:59:72 | ...::format(...) | semmle.label | ...::format(...) |
|
||||
| sqlx.rs:59:17:59:72 | ...::must_use(...) | semmle.label | ...::must_use(...) |
|
||||
| sqlx.rs:59:17:59:72 | MacroExpr | semmle.label | MacroExpr |
|
||||
| sqlx.rs:59:17:59:72 | { ... } | semmle.label | { ... } |
|
||||
| sqlx.rs:77:13:77:23 | ...::query | semmle.label | ...::query |
|
||||
| sqlx.rs:77:25:77:36 | safe_query_3 | semmle.label | safe_query_3 |
|
||||
| sqlx.rs:77:25:77:45 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() |
|
||||
@@ -94,4 +116,8 @@ nodes
|
||||
| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() [&ref] | semmle.label | unsafe_query_1.as_str() [&ref] |
|
||||
| sqlx.rs:80:17:80:27 | ...::query | semmle.label | ...::query |
|
||||
| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() [&ref] | semmle.label | unsafe_query_2.as_str() [&ref] |
|
||||
| sqlx.rs:82:17:82:27 | ...::query | semmle.label | ...::query |
|
||||
| sqlx.rs:82:29:82:42 | unsafe_query_4 | semmle.label | unsafe_query_4 |
|
||||
| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() |
|
||||
| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() [&ref] | semmle.label | unsafe_query_4.as_str() [&ref] |
|
||||
subpaths
|
||||
|
||||
@@ -79,7 +79,7 @@ async fn test_sqlx_mysql(url: &str, enable_remote: bool) -> Result<(), sqlx::Err
|
||||
if enable_remote {
|
||||
let _ = sqlx::query(unsafe_query_2.as_str()).execute(&pool).await?; // $ sql-sink Alert[rust/sql-injection]=remote1
|
||||
let _ = sqlx::query(unsafe_query_3.as_str()).execute(&pool).await?; // $ sql-sink MISSING: Alert[rust/sql-injection]=remote1
|
||||
let _ = sqlx::query(unsafe_query_4.as_str()).execute(&pool).await?; // $ sql-sink MISSING: Alert[rust/sql-injection]=remote1
|
||||
let _ = sqlx::query(unsafe_query_4.as_str()).execute(&pool).await?; // $ sql-sink Alert[rust/sql-injection]=remote1
|
||||
}
|
||||
let _ = sqlx::query(prepared_query_1.as_str()).bind(const_string).execute(&pool).await?; // $ sql-sink
|
||||
let _ = sqlx::query(prepared_query_1.as_str()).bind(arg_string).execute(&pool).await?; // $ sql-sink
|
||||
|
||||
@@ -919,6 +919,15 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
signature module SatisfiesConstraintInputSig<HasTypeTreeSig HasTypeTree> {
|
||||
/** Holds if it is relevant to know if `term` satisfies `constraint`. */
|
||||
predicate relevantConstraint(HasTypeTree term, Type constraint);
|
||||
|
||||
/**
|
||||
* Holds if constraints that are satisfied through conditions that are
|
||||
* universally quantified type parameters should be used. Such type
|
||||
* parameters might have type parameter constraints, and these are _not_
|
||||
* checked. Hence using these represent a trade-off between too many
|
||||
* constraints and too few constraints being satisfied.
|
||||
*/
|
||||
default predicate useUniversalConditions() { any() }
|
||||
}
|
||||
|
||||
module SatisfiesConstraint<
|
||||
@@ -961,6 +970,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
TypeMention constraintMention
|
||||
) {
|
||||
exists(Type type | hasTypeConstraint(tt, type, constraint) |
|
||||
useUniversalConditions() and
|
||||
not exists(countConstraintImplementations(type, constraint)) and
|
||||
conditionSatisfiesConstraintTypeAt(abs, condition, constraintMention, _, _) and
|
||||
resolveTypeMentionRoot(condition) = abs.getATypeParameter() and
|
||||
|
||||
Reference in New Issue
Block a user