[BUG] device_info() buffers are 64 bytes; CUDA backend writes 257, corrupting the stack
まだ誰も着手していません。
評価
調査の方向性
src/core/device.rs:109-121 から始め、device_info() に渡されるバッファを調べます。これらを文書化された契約および src/backend/cuda/platform.cpp:290-307 に記載された CUDA の動作と比較します。CUDA バックエンドで examples/helloworld.rs を実行して呼び出しが安全であることを確認し、device_info() によって CUDA バックエンドが呼び出し元のスタックを上書きできなくなった時点で issue の完了とします。
索引モデルが issue の本文から書いたものです。
説明
Description
device_info() allocates the buffer sizes recommended by the ArrayFire documentation, but the CUDA backend writes up to 257 bytes into the first one. On the CUDA backend this corrupts up to 193 bytes of the caller's stack on every call.
This is a plausible root cause for several long-standing crash reports here: #106, #285, #311.
pub fn device_info() -> (String, String, String, String) {
let mut name: [c_char; 64] = [0; 64];
let mut platform: [c_char; 10] = [0; 10];
let mut toolkit: [c_char; 64] = [0; 64];
let mut compute: [c_char; 10] = [0; 10];
unsafe {
let err_val = af_device_info(
&mut name[0], &mut platform[0], &mut toolkit[0], &mut compute[0],
);
These sizes match ArrayFire's documented contract exactly (docs/details/device.dox:10-16, "Recommended minimum size is 64 / 10 / 64 / 10" across the four params), and af_device_info takes no length arguments, so there is nothing else to go on.
The CUDA backend does not honour it (src/backend/cuda/platform.cpp:290-307, identical from 3.8.0 through master):
snprintf(d_name, 256, "%s", dev.name);
// Sanitize input
for (int i = 0; i < 256; i++) {
if (d_name[i] == ' ') { // reads d_name[0..256]
if (d_name[i + 1] == 0 || d_name[i + 1] == ' ') {
d_name[i] = 0; // writes d_name[0..255]
} else {
d_name[i] = '_';
}
}
}
The sanitize loop does not stop at the NUL terminator, so it runs the full 256 iterations regardless of the actual device-name length, writing 0x00 or '_' wherever it reads a 0x20 byte. The overflow therefore is not conditional on having a long GPU name — it happens on every call.
The CPU and OpenCL backends are correct here (snprintf(..., 64, ...), and OpenCL bounds its sanitize loop at i < 31), so this affects the CUDA backend only — which matches the reported pattern of crashes that disappear when users switch to CPU or OpenCL.
I've filed the backend-side bug upstream as arrayfire/arrayfire#<CPP_ISSUE>.
Impact
Writing ~193 bytes past a stack array clobbers the other three buffers, spilled registers, the /GS cookie and the return address. On Windows that surfaces as STATUS_ACCESS_VIOLATION (0xC0000005) or STATUS_STACK_BUFFER_OVERRUN (0xC0000409).
The corruption is deterministic but the crash is intermittent, because whether it is fatal depends on which stack bytes happen to contain 0x20 and on the frame layout rustc chose. That also gives a mechanism for #299 (crash only at opt-level = 3): more aggressive inlining means less dead stack padding to absorb the overflow.
examples/helloworld.rs:9 calls device_info(), so this is in the first program a new user runs.
Reproducible Code and/or Steps
see above
System Information
general code issue, system independent
Checklist
- Using the latest available ArrayFire release
- GPU drivers are up to date
Suggested fix
Independent of any upstream change, and safe against every 3.8.x:
let mut name: [c_char; 1024] = [0; 1024];
(or at least 257)
Happy to open a PR if that's useful.
Disclaimer
Found by Claude Opus 5 while investigating intermittent 0xC0000005 errors on Windows/CUDA. I checked this manually and it seems like a real bug.
- 主要言語
- Rust
- スター
- 827
- フォーク
- 59
- PR マージ指標
- 30日以内にマージされた PR はありません
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
arrayfire/arrayfire-rust のほかの issue
-
Bug
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
arrayfire/arrayfire-rust#388 ·
-
Bug
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
arrayfire/arrayfire-rust#387 ·
-
Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
arrayfire/arrayfire-rust#386 ·
-
Bug
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
arrayfire/arrayfire-rust#385 · コメント 1 件 ·
-
Bug
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
arrayfire/arrayfire-rust#382 ·
arrayfire/arrayfire-rust の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
gitbutlerapp/gitbutler#15998 · コメント 1 件 ·
-
bug triage:deciding
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
open-telemetry/otel-arrow#4132 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100