[BUG] device_info() buffers are 64 bytes; CUDA backend writes 257, corrupting the stack

Đang mở Phù hợp với người mới
#384 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
76/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
rust
Lĩnh vực
backend

Hướng nghiên cứu

Bắt đầu tại src/core/device.rs:109-121 và kiểm tra các buffer được truyền vào device_info(); so sánh chúng với hợp đồng được ghi lại và hành vi CUDA được mô tả trong src/backend/cuda/platform.cpp:290-307. Chạy examples/helloworld.rs với backend CUDA để xác nhận rằng lời gọi là an toàn, và coi issue là hoàn tất khi device_info() không còn cho phép backend CUDA ghi đè stack của bên gọi.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Bug

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.

src/core/device.rs:109-121:

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.

Ngôn ngữ chính
Rust
Star
827
Fork
59
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của arrayfire/arrayfire-rust

Tất cả issue của arrayfire/arrayfire-rust

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.