Bug and fix: `core::fmt` hangs with formatting flags (`{:#x}`, `{:#o}`, `{:#b}`, etc.)
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
从列出的三个路径中的 compiler-builtins/src/int/bswap.rs 开始,然后通过 run.sh 重现格式化用例,并检查生成的调用链。验证 bswap 实现在 rustc_codegen_gcc 下不再递归,并且 alternate、alignment 和 padding 示例能够在不挂起的情况下完成。
由索引模型根据 Issue 内容生成。
描述
Symptoms
When using formatting flags with an alternate flag or alignment/padding, the program hangs, produces no output, and raises no exception:
println!("{:#x}", 42u32); // hangs
println!("{:#010x}", 42u32); // hangs
println!("{:>10}", 42u32); // hangs
println!("{:x}", 42u32); // works normally
println!("{}", 42u32); // works normally
Root Cause
bswap.rs in compiler_builtins uses #[maybe_use_optimized_c_shim] + x.swap_bytes():
rust
// Original code (problematic)
#[maybe_use_optimized_c_shim]
pub extern "C" fn __bswapsi2(x: u32) -> u32 {
x.swap_bytes() // ← rustc_codegen_gcc compiles this into a call to __bswapsi2 itself
}
rustc_codegen_gcc compiles u32::swap_bytes() into a function call to __bswapsi2, leading to:
text
__bswapsi2 → ___bswapsi2 → __bswapsi2 → ___bswapsi2 → ... (infinite recursion)
After stack overflow, the PC jumps to an invalid address (e.g., 0xfb079370), causing the program to hang.
Inside core::fmt, handling the alternate flag (#) calls pad_integral, which in turn triggers __bswapsi2, exposing this bug.
Debugging Process
QEMU -d exec revealed the program stuck at 0x0dfc (OpenRISC exception vector area)
Vector 0xC00 = syscall exception, triggered by l.sys 0x8060
GDB breakpoint at 0xC00, ppc = 0x26914, located in the __bswapsi2 call chain
Disassembly showed mutual recursion: __bswapsi2 → ___bswapsi2 → __bswapsi2
Files to Modify
The bswap.rs files in the following three paths have identical content (same md5) and all need modification:
text
~/or1k-build/rustc_codegen_gcc/build/build_sysroot/sysroot/lib/rustlib/src/rust/library/compiler-builtins/compiler-builtins/src/int/bswap.rs
~/or1k-build/rustc_codegen_gcc/build/build_sysroot/sysroot_src/library/compiler-builtins/compiler-builtins/src/int/bswap.rs
~/or1k-build/rust-src/library/compiler-builtins/compiler-builtins/src/int/bswap.rs
The actual path used by run.sh (with -Z build-std=core) is the stage1 sysroot path, which can be confirmed with:
bash
find ~/or1k-build/rust-src/build -name "bswap.rs" -path "*/compiler-builtins/*" 2>/dev/null
Fix
Replace x.swap_bytes() with pure shift operations to eliminate recursion:
bash
# Backup (all three paths have identical content, backup together)
find /home/openrisc/or1k-build -name "bswap.rs" -path "*/compiler-builtins/*" | \
while read f; do cp "$f" "${f}.bak"; echo "Backed up: $f"; done
# Modify (apply to all three paths)
find /home/openrisc/or1k-build -name "bswap.rs" -path "*/compiler-builtins/*" \
! -name "*.bak" | while read f; do
cat > "$f" << 'BSWAP_EOF'
intrinsics! {
pub extern "C" fn __bswapsi2(x: u32) -> u32 {
((x & 0x000000FFu32) << 24) |
((x & 0x0000FF00u32) << 8) |
((x & 0x00FF0000u32) >> 8) |
((x & 0xFF000000u32) >> 24)
}
pub extern "C" fn __bswapdi2(x: u64) -> u64 {
((x & 0x00000000000000FFu64) << 56) |
((x & 0x000000000000FF00u64) << 40) |
((x & 0x0000000000FF0000u64) << 24) |
((x & 0x00000000FF000000u64) << 8) |
((x & 0x000000FF00000000u64) >> 8) |
((x & 0x0000FF0000000000u64) >> 24) |
((x & 0x00FF000000000000u64) >> 40) |
((x & 0xFF00000000000000u64) >> 56)
}
pub extern "C" fn __bswapti2(x: u128) -> u128 {
let hi = ((x >> 64) & 0xFFFFFFFFFFFFFFFFu128) as u64;
let lo = (x & 0xFFFFFFFFFFFFFFFFu128) as u64;
let hi_swapped = __bswapdi2(hi) as u128;
let lo_swapped = __bswapdi2(lo) as u128;
(lo_swapped << 64) | hi_swapped
}
}
BSWAP_EOF
echo "Modified: $f"
done
# Clear compilation cache to trigger recompilation
find ~/riscion/sw/rust/testfmt/target -name "*compiler_builtins*" -delete
After modification, simply re-run run.sh. This fix must be reapplied after upgrading the nightly version.
Impact Scope
All code using core::fmt with alternate/alignment/padding formatting flags, including but not limited to:
{:#x}, {:#X}, {:#o}, {:#b}
{:#010x} and other width-specified alternate formats
{:>10}, {:<10}, {:^10} and other alignment formats
{:*^12}, {:0>8} and other custom padding formats
- 主要语言
- Rust
- 星标
- 1.2k
- 派生
- 106
- 平均合并
- 11 小时 14 分钟
- 30 天内合并 PR
- 25
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
rust-lang/rustc_codegen_gcc 的其他 Issue
-
tests
难度 2/5 1-3 小时 新手友好度 62/100
rust-lang/rustc_codegen_gcc#993 ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 55/100
rust-lang/rustc_codegen_gcc#1020 ·
维护者通常 1 天内回复
-
Cannot compile sysroot if having a build.build-dir cargo config可能已有人在做 @GuillaumeGomez 于 12 天前认领。 未关闭
rust-lang/rustc_codegen_gcc#1011 · 1 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
tests
难度 4/5 3-5 天 新手友好度 30/100
rust-lang/rustc_codegen_gcc#992 ·
维护者通常 1 天内回复
-
bug
难度 5/5 一周以上 新手友好度 35/100
rust-lang/rustc_codegen_gcc#970 · 5 条评论 ·
维护者通常 1 天内回复
查看 rust-lang/rustc_codegen_gcc 的全部 Issue
相似的 Issue
-
难度 1/5 1-3 小时 新手友好度 70/100
OpenZeppelin/openzeppelin-relayer#967 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
src/runs.rs:1987: a missing --source-run-id now answers 400 "Source run ... does not exist", not 404未关闭nightly-audit
难度 2/5 1-3 小时 新手友好度 62/100
antithesishq/snouty#602 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 70/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 70/100
libnativeapi/nativeapi#21 ·