Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added `ExtractedFile::hasSemantics` and `ExtractedFile::isSkippedByCompilation` predicates.
19 changes: 19 additions & 0 deletions rust/ql/lib/codeql/files/FileSystem.qll
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ class File extends Container, Impl::File {
*/
class ExtractedFile extends File {
ExtractedFile() { this.fromSource() }

private Diagnostic getNoSemanticsDiagnostic() {
result.getTag() = "semantics" and result.getLocation().getFile() = this
}

/**
* Holds if we have semantical information about this file, which means
* we should be able to
* * expand any macros
* * skip any blocks that are conditionally compiled out
*/
predicate hasSemantics() { not exists(this.getNoSemanticsDiagnostic()) }

/**
* Holds if we know this file was skipped by conditional compilation.
* This is not the same as `not this.hasSemantics()`, as a file
* might not have semantics because of some error.
*/
predicate isSkippedByCompilation() { this.getNoSemanticsDiagnostic().getSeverityText() = "Info" }
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extractionWarning
| bad_cargo/src/no_semantics.rs:1:1:1:1 | semantic analyzer unavailable (unable to load manifest) |
15 changes: 9 additions & 6 deletions rust/ql/test/extractor-tests/File/File.expected
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
| Cargo.toml:0:0:0:0 | Cargo.toml | fromSource: no |
| a_file.rs:0:0:0:0 | a_file.rs | fromSource: yes |
| another_file.rs:0:0:0:0 | another_file.rs | fromSource: yes |
| lib.rs:0:0:0:0 | lib.rs | fromSource: yes |
| nested.rs:0:0:0:0 | nested.rs | fromSource: yes |
| nested/file.rs:0:0:0:0 | nested/file.rs | fromSource: yes |
| Cargo.toml:0:0:0:0 | Cargo.toml | fromSource: no | hasSemantics: no | isSkippedByCompilation: no |
| a_file.rs:0:0:0:0 | a_file.rs | fromSource: yes | hasSemantics: yes | isSkippedByCompilation: no |
| another_file.rs:0:0:0:0 | another_file.rs | fromSource: yes | hasSemantics: yes | isSkippedByCompilation: no |
| bad_cargo/Cargo.toml:0:0:0:0 | bad_cargo/Cargo.toml | fromSource: no | hasSemantics: no | isSkippedByCompilation: no |
| bad_cargo/src/no_semantics.rs:0:0:0:0 | bad_cargo/src/no_semantics.rs | fromSource: yes | hasSemantics: no | isSkippedByCompilation: no |
| lib.rs:0:0:0:0 | lib.rs | fromSource: yes | hasSemantics: yes | isSkippedByCompilation: no |
| nested.rs:0:0:0:0 | nested.rs | fromSource: yes | hasSemantics: yes | isSkippedByCompilation: no |
| nested/file.rs:0:0:0:0 | nested/file.rs | fromSource: yes | hasSemantics: yes | isSkippedByCompilation: no |
| nested/not_compiled.rs:0:0:0:0 | nested/not_compiled.rs | fromSource: yes | hasSemantics: no | isSkippedByCompilation: yes |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my education: what (in the Cargo setup) makes file.rs compiled while not_compiled.rs is not?

Copy link
Contributor Author

@redsun82 redsun82 Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not pulled in as a module.

By default:

  • cargo loads src/lib.rs (for libraries) or src/main.rs (for binaries)
  • for a mod x in those, it will load either src/x.rs or src/x/mod.rs
  • from then on, for each submodule mod z in a x::y module, it will look for either src/x/y/z.rs or src/x/y/z/mod.rs (i.e. submodules are loaded from a directory recreating the module nesting)

If a file is not mentioned by a mod, or if its mention is not compiled because of a cfg setting, then the file is never loaded. There are ways to bypass the default paths (path settings in cargo.toml or path attributes of mod in code), but that's the gist of the file compilation strategy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so it's File/ in the path that identifies file.rs as special.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's mod file; in nested.rs that includes that

14 changes: 11 additions & 3 deletions rust/ql/test/extractor-tests/File/File.ql
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import rust

from File f, string fromSource
from File f, string fromSource, string hasSemantics, string isSkippedByCompilation
where
exists(f.getRelativePath()) and
if f.fromSource() then fromSource = "fromSource: yes" else fromSource = "fromSource: no"
select f, fromSource
(if f.fromSource() then fromSource = "fromSource: yes" else fromSource = "fromSource: no") and
(
if f.(ExtractedFile).hasSemantics()
then hasSemantics = "hasSemantics: yes"
else hasSemantics = "hasSemantics: no"
) and
if f.(ExtractedFile).isSkippedByCompilation()
then isSkippedByCompilation = "isSkippedByCompilation: yes"
else isSkippedByCompilation = "isSkippedByCompilation: no"
select f, fromSource, hasSemantics, isSkippedByCompilation
1 change: 1 addition & 0 deletions rust/ql/test/extractor-tests/File/bad_cargo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!/Cargo.toml
1 change: 1 addition & 0 deletions rust/ql/test/extractor-tests/File/bad_cargo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
wrong
Empty file.
Empty file.