Rust: modules declared in a file brought in by `include!` are not resolved (no canonical paths, unresolved calls), e.g. in `windows-sys` and `windows`
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 47/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- rust
- 领域
- compilers, testing-qa
调研方向
Start with text_range_for_node in rust/extractor/src/translate/base.rs and modImport0 in codeql/rust/internal/PathResolution.qll; compare how the included tree/mod.rs and its inner module are extracted with the normally declared direct module. Reproduce with the supplied two-crate workspace and query, then check that hidden and hidden_extern receive canonical paths and their calls resolve like the control module.
由索引模型根据 Issue 内容生成。
描述
Description of the issue
When a crate's lib.rs brings in part of its module tree with include!("tree/mod.rs"), and that file declares pub mod inner;, CodeQL looks for inner next to lib.rs instead of next to tree/mod.rs, where rustc finds it. As a result, nothing in inner gets a canonical path, calls into it have no getStaticTarget(), and models-as-data rows for its functions never apply.
The public windows-sys and windows crates are built this way (lib.rs contains include!("Windows/mod.rs")), so Windows API calls made through them are never resolved:
windows-sys0.61.2: 0 of the 10,661 functions undersrc/Windows/Win32have a canonical path.windows0.62.2: 777 of 130,113 do (withcodeql/rust-all0.2.25);CreateFileWis not among them.- Calls to
CreateFileW,ReadFile,RegQueryValueExW,CreateProcessW,ShellExecuteWandrecvthroughwindows-sys, and to the first four throughwindows, are unresolved.
Seen with CodeQL 2.27.2 (codeql/rust-all 0.2.23) and 2.27.4 (codeql/rust-all 0.2.25), Rust 1.99.0, Windows x64. Setting extract_dependencies_as_source=true does not change it.
Reproduction
A two-crate workspace. toy-include brings in module inner through include!; module direct, declared normally, has the same contents and serves as a control.
Cargo.toml
[workspace]
members = ["toy-include", "toy-user"]
resolver = "2"
toy-include/Cargo.toml
[package]
name = "toy-include"
version = "0.1.0"
edition = "2021"
toy-include/src/lib.rs
macro_rules! declare {
($name:ident) => {
extern "C" {
pub fn $name() -> u32;
}
};
}
include!("tree/mod.rs");
pub mod direct;
toy-include/src/tree/mod.rs
pub mod inner;
toy-include/src/tree/inner/mod.rs
pub fn hidden() -> u32 {
1
}
declare!(hidden_extern);
toy-include/src/direct.rs
pub fn visible() -> u32 {
2
}
declare!(visible_extern);
toy-user/Cargo.toml
[package]
name = "toy-user"
version = "0.1.0"
edition = "2021"
[dependencies]
toy-include = { path = "../toy-include" }
toy-user/src/main.rs
fn main() {
let a = toy_include::inner::hidden();
let b = toy_include::direct::visible();
let c = unsafe { toy_include::inner::hidden_extern() };
let d = unsafe { toy_include::direct::visible_extern() };
println!("{}", a + b + c + d);
}
The workspace builds with cargo check. Query (query/qlpack.yml depends on codeql/rust-all: "*"):
query/include-paths.ql
import rust
/** Each function of the `toy-include` crate, with its canonical path (none if CodeQL gives none). */
query predicate functions(string file, string name, string canonicalPath) {
exists(Function f |
f.getFile().getAbsolutePath().matches("%toy-include%") and
file = f.getFile().getAbsolutePath().regexpCapture(".*toy-include[/\\\\]src[/\\\\](.*)", 1) and
name = f.getName().getText() and
if exists(f.getCanonicalPath()) then canonicalPath = f.getCanonicalPath() else canonicalPath = "(none)"
)
}
/** Each call in the program, with the function it resolves to (none if unresolved). */
query predicate calls(int line, string call, string target) {
exists(Call c | c.getFile().getBaseName() = "main.rs" |
line = c.getLocation().getStartLine() and
call = c.toString() and
if exists(c.getStaticTarget())
then target = c.getStaticTarget().getCanonicalPath()
else target = "(unresolved)"
)
}
select 1
Run:
codeql database create db --language=rust --source-root=.
codeql query run query/include-paths.ql --database=db --output=out.bqrs
codeql bqrs decode out.bqrs --format=csv --result-set=functions
codeql bqrs decode out.bqrs --format=csv --result-set=calls
Expected: hidden and hidden_extern have the canonical paths toy_include::inner::hidden and toy_include::inner::hidden_extern, and the calls on lines 2 and 4 resolve to them, like the control module's.
Actual:
"file","name","canonicalPath"
"direct.rs","visible","toy_include::direct::visible"
"direct.rs","visible_extern","toy_include::direct::visible_extern"
"tree/inner/mod.rs","hidden","(none)"
"tree/inner/mod.rs","hidden_extern","(none)"
"line","call","target"
2,"...::hidden(...)","(unresolved)"
3,"...::visible(...)","toy_include::direct::visible"
4,"...::hidden_extern(...)","(unresolved)"
5,"...::visible_extern(...)","toy_include::direct::visible_extern"
Likely cause
- In the extractor,
text_range_for_node(rust/extractor/src/translate/base.rs) keeps a node's location only if it maps into the file being extracted. Nodes produced by aninclude!map into the included file, so theinnermodule in the expansion reportslib.rsas its file. modImport0incodeql/rust/internal/PathResolution.qllthen looks formod inner;relative tolib.rs(src/inner.rs,src/inner/mod.rs) instead ofsrc/tree/.tree/mod.rsis also extracted on its own, and theremod inner;does resolve, but that copy is not part of the crate's module tree.
A possible fix: have the extractor give include!d nodes their locations in the included file (or record which file each include! includes), so that mod files are looked up next to the file that declares them.
- 主要语言
- CodeQL
- 星标
- 10.3k
- 派生
- 2.1k
- 平均合并
- 2 天 6 小时
- 30 天内合并 PR
- 137
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
github/codeql 的其他 Issue
-
JavaScript externs model StorageEvent() with no type argument可能已有人在做 @asgerf 于 15 天前认领。 未关闭false-positive javascript
难度 2/5 1-3 小时 新手友好度 84/100
github/codeql#22632 · 3 条评论 · 1 个 reaction · 已指派 2 人 ·
维护者通常 1 天内回复
-
Add AlertSuppression.ql for Rust (inline // codeql[...] suppression)可能已有人在做 @cnuss 于 216 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
false-positive
难度 2/5 1-3 小时 新手友好度 70/100
github/codeql#21076 · 3 条评论 · 3 个 reaction ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 47/100
维护者通常 1 天内回复
-
False positive java/local-variable-is-never-read for Kotlin data object-generated equals temporaries未关闭false-positive
难度 4/5 3-5 天 新手友好度 35/100
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
-
bug stdlib
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
0.kind: enhancement 9.needs: package (update)
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
S3: friction & debt ws:tooling
难度 2/5 1-3 小时 新手友好度 82/100
MedakaLang/medaka#4865 ·
维护者通常 1 天内回复
-
subsystem: saw-core type: bug
难度 2/5 1-3 小时 新手友好度 65/100
GaloisInc/saw-script#3516 ·
维护者通常 1 天内回复