[Rust] Get type of expression
Description of the issue
How do I get the type of an expression in Rust?
For example, I want to constrain this to only accesses on string-like expressions.
private class IndexExprOnNonConstantString extends IndexExpr {
IndexExprOnNonConstantString() { not this.getBase() instanceof StringLiteralExpr }
}
Actual: No getType predicate on expr.
Expected: Predicate to get type of expr.
When will support be added for an - in my understanding - very basic feature? Or is there a workaround/internal API?
Hi @intrigus-lgtm 👋🏻
The way that Rust support for CodeQL is implemented is a bit different from other languages, which means that types aren't extracted and so cannot easily be queried. There is an internal API that implements type inference in rust/ql/test/library-tests/type-inference/type-inference.ql that you may be able to use.
Small correction, the QL-based type inference is in rust/ql/lib/codeql/rust/internal/TypeInference.qll.
It's not a public API and doesn't work in the same way that a public API would, but something like the thing you're going for can be implemented like this:
private class IndexExprOnNonConstantString extends IndexExpr {
IndexExprOnNonConstantString() {
not inferType(this.getBase()).(StructType).asItemNode() instanceof StringStruct
}
}
`
Hi @intrigus-lgtm 👋🏻
The way that Rust support for CodeQL is implemented is a bit different from other languages, which means that types aren't extracted and so cannot easily be queried. There is an internal API that implements type inference in
rust/ql/test/library-tests/type-inference/type-inference.qlthat you may be able to use.
(Sorry for the late reply) But there will be a public API in the future, right? OOI: is there a reason why you cannot (re-)use the types that rust-analyzer (?) computes?
Small correction, the QL-based type inference is in rust/ql/lib/codeql/rust/internal/TypeInference.qll.
It's not a public API and doesn't work in the same way that a public API would, but something like the thing you're going for can be implemented like this:
private class IndexExprOnNonConstantString extends IndexExpr { IndexExprOnNonConstantString() { not inferType(this.getBase()).(StructType).asItemNode() instanceof StringStruct } } `
I tried that API and while it works for some cases, it didn't work for the actually interesting cases I was interested in :( Should I open an issue for those cases?
For example
predicate debug(IndexExpr ie, string baseType) {
ie.getLocation().getFile().getBaseName() = "validator.rs" and
if not exists(inferType(ie.getBase()))
then baseType = "none"
else baseType = inferType(ie.getBase()).toString()
}
doesn't return results for details[...] (line 1443) in 8697007af8c99fa788c39c898f9ea945c2212f40 of https://github.com/firedancer-io/agave/tree/v2.3.6-fd
There might be a public API in the future, though I don't think it's a priority right now as we haven't needed it for our queries.
OOI: is there a reason why you cannot (re-)use the types that rust-analyzer (?) computes?
We only use rust-analyzer for parsing and macro expansion. We ran into performance issues when using it for other things, so that's why we currently infer types in QL.
doesn't return results for details[...] (line 1443) in 8697007af8c99fa788c39c898f9ea945c2212f40 of https://github.com/firedancer-io/agave/tree/v2.3.6-fd
Sorry, in which file? Can you post a link directly to the line?
There might be a public API in the future, though I don't think it's a priority right now as we haven't needed it for our queries.
So how would you write a query that checks slicing into strings at non-char boundaries like this:
let indirect_str = "A👋🌍!";
// let indirect_str = remote_source();
let indirect_str = &indirect_str[0..2]; // panics, because 2 is not a char boundary
println!("indirect_str: {}", indirect_str);
I currently see no way to restrict IndexExpr-s to only those that operate on strings.
CodeQL Rust feels like an alpha in some places. If you have high-level stuff like function calls, taint flowing from a to b it's pretty nice (and I guess that's what you've written most of your queries for?), but as soon as you get a bit more low-level and closer to the AST it feels a bit bare-bones.
OOI: is there a reason why you cannot (re-)use the types that rust-analyzer (?) computes?
We only use rust-analyzer for parsing and macro expansion. We ran into performance issues when using it for other things, so that's why we currently infer types in QL.
doesn't return results for details[...] (line 1443) in 8697007af8c99fa788c39c898f9ea945c2212f40 of https://github.com/firedancer-io/agave/tree/v2.3.6-fd
Sorry, in which file? Can you post a link directly to the line?
Apologies, I thought it would be more obvious from the debug predicate, that I meant this file (my fault): https://github.com/firedancer-io/agave/blob/8697007af8c99fa788c39c898f9ea945c2212f40/core/src/validator.rs#L1443
CodeQL Rust feels like an alpha in some places. If you have high-level stuff like function calls, taint flowing from a to b it's pretty nice (and I guess that's what you've written most of your queries for?), but as soon as you get a bit more low-level and closer to the AST it feels a bit bare-bones.
I think that is a very fair and accurate assessment. Note that Rust support was just released, so it is still the youngest language and far from as mature as the others.
Apologies, I thought it would be more obvious from the debug predicate, that I meant this file (my fault): https://github.com/firedancer-io/agave/blob/8697007af8c99fa788c39c898f9ea945c2212f40/core/src/validator.rs#L1443
From a quick look I can't see why we're not inferring types there. But, type inference has known gaps which we're actively working towards closing.