codeql icon indicating copy to clipboard operation
codeql copied to clipboard

[Rust] Get type of expression

Open intrigus-lgtm opened this issue 3 months ago • 7 comments

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?

intrigus-lgtm avatar Sep 22 '25 12:09 intrigus-lgtm

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.

mbg avatar Sep 22 '25 15:09 mbg

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
  }
}
`

paldepind avatar Sep 22 '25 16:09 paldepind

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.

(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?

intrigus-lgtm avatar Sep 29 '25 20:09 intrigus-lgtm

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

intrigus-lgtm avatar Sep 29 '25 20:09 intrigus-lgtm

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?

paldepind avatar Sep 30 '25 07:09 paldepind

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

intrigus-lgtm avatar Sep 30 '25 12:09 intrigus-lgtm

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.

paldepind avatar Oct 21 '25 13:10 paldepind