-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Rust: Reduce the number of sinks in DereferenceSink
#20941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: Reduce the number of sinks in DereferenceSink
#20941
Conversation
b569633 to
40f629e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds barriers and refines sink definitions to reduce false positives in the rust/access-invalid-pointer query. The changes separate concerns between the AccessInvalidPointer and AccessAfterLifetime queries by giving each its own sink definitions with appropriate restrictions.
- Adds type-based barriers (numeric, boolean, fieldless enum) to filter out non-pointer types
- Restricts
DereferenceSinkinAccessInvalidPointerto only match raw pointer dereferences in unsafe contexts - Introduces a
DefaultBarrierto handle impreciseDefault::defaultcalls that can resolve to null pointer implementations
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
rust/ql/src/queries/summary/Stats.qll |
Adds import for AccessAfterLifetimeExtensions to ensure all query sink extensions are loaded |
rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll |
Adds multiple barriers (type-based, NonNull::new, Default::default) and restricts DereferenceSink to unsafe contexts with raw pointer type checks |
rust/ql/lib/codeql/rust/security/AccessAfterLifetimeExtensions.qll |
Refactors Sink from type alias to abstract class and defines its own sink implementations separate from AccessInvalidPointer |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
Outdated
Show resolved
Hide resolved
rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
Outdated
Show resolved
Hide resolved
rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
Outdated
Show resolved
Hide resolved
35cf657 to
0b3a694
Compare
| // TODO: Remove this condition if it can be done without negatively | ||
| // impacting performance. This condition only include nodes with | ||
| // corresponding to an expression. This excludes sinks from models-as-data. | ||
| exists(node.asExpr()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is weird, but note that the check before the changes had the same effect of excluding all nodes without an expression. So this is only preserving what was already there.
Since my present goal is to improve performance I don't really have appetite for introducing additional sinks, hence I left this condition in place.
As the todo says I think we should try to remove this in the future and see what it does for performance and results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could re-include the models-as-data sinks explicitly with something like:
or
node instanceof AccessAfterLifetime::ModelsAsDataSink
There ought not be too many of these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we might as well remove the line. I don't think it does much beside exclude MaD sinks.
My concern is that we have 318 pointer-access MaD sinks (most are generated). These are currently not used by the query, and starting to use them might cause problems that I'd like not to block other work. I'd rather we try that after getting the model generator working again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think its the right move to remove all the MaD sinks, but I appreciate that the model generator work is in progress and the TODO comment calls this out. I'd also prefer a more explicit not node instanceof AccessAfterLifetime::ModelsAsDataSink over exists(node.asExpr()), but then we need to make ModelsAsDataSink public.
I think I've come round to accepting this, for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think its the right move to remove all the MaD sinks
Just to be clear, the MaD sinks where already removed/excluded. This exists(..) is to preserve things as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I hadn't spotted that. Explains why it didn't affect results!
rust/access-invalid-pointerDereferenceSink
|
Thanks for the review @geoffw0. I've now updated the PR to (almost) only include the change to |
49b7338 to
ef8d2c0
Compare
geoffw0
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed the QL and I'm happy from that point of view. I think I've figured out where I stand regarding the sink restrictions now - see the PR onto this PR - basically, losing a few mostly theoretical results is an acceptable cost to get the noise down. I've still to review your MRVA results and think about a few other details.
f3621fe to
c5a44cf
Compare
|
DCA - I'm happy that the removed results in your runs appear to be FPs, most are of the form
|
|
Thanks for reviewing and for the additional test case.
Fixed by rebasing on |
This PR reduces the number of sinks in
DereferenceSinkby not including dereference expressions that are not the source of unsafety.The
DereferenceSinkis used inrust/access-invalid-pointerandrust/access-after-lifetime-ended.The number of sinks is reduced in two ways:
unsafeblock. Onrustthis restriction reduces the number of sinks from 29,857 to 1,618. This filter was already applied inrust/access-after-lifetime-endedso it only makes a difference for therust/access-invalid-pointerquery.rustthis further reduces the number of sinks from 1,618 to 1,301.I've looked at some of the sink that are removed on
rustdue to the type check, and they look like good exclusions to me. Here's a typical example:This deref is excluded because
get_uncheckedreturns a&. Excluding this seem fine because 1/ the query can't handle this anyway and 2/ if the aboveunsafeblock goes wrong the root cause for blame is withinget_uncheckedand not*.MRVA
MRVA top 100 for "Access of invalid pointer"
Overall there's only a small change in the number of results, which seems good. The removed results that I've looked at all seemed like FPs.