Closed
Description
Hello,
A cast of a u16 value returned from a C function to a usize is invalid when enabling optimization.
I tried this code (with cargo flag --release):
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
struct bloc {
uint16_t a;
uint16_t b;
uint16_t c;
};
uint16_t c_read_value(void) {
struct bloc *data = malloc(sizeof(struct bloc));
data->a = rand() & 0xFFFF;
data->b = rand() & 0xFFFF;
data->c = rand() & 0xFFFF;
printf("C struct: a = %u, b = %u, c = %u\n",
(unsigned) data->a, (unsigned) data->b, (unsigned) data->c);
printf("C function returns %u\n", (unsigned) data->b);
return data->b; /* leak data */
}
//#![feature(bench_black_box)]
#[link(name = "bad")]
extern "C" {
pub fn c_read_value() -> u16;
}
fn main() {
let value = unsafe { c_read_value() };
dbg!(value); // ok
dbg!(value as usize); // nok
dbg!(usize::from(value)); // nok
dbg!((value as usize) & 0xFFFF); // nok
//dbg!(std::hint::black_box(value) as usize); // ok
}
I expected to print the same value when casting to usize.
Instead, the value is wrong, the cast seems to "absorb" the neighboring bytes. Worse, I cannot even mask with & 0xFFFF
!
C struct: a = 17767, b = 9158, c = 39017
C function returns 9158
[src/main.rs:10] value = 9158
[src/main.rs:11] value as usize = 846930886
[src/main.rs:12] usize::from(value) = 846930886
[src/main.rs:13] (value as usize) & 0xFFFF = 846930886
Using black_box with nightly on the value fixes the issue. I'd like to find a good workaround for stable though.
No issue in debug mode.
To reproduce, this repo can be used: https://github.com/fparat/badcast
Meta
Bug present on stable and nightly.
Found on Linux aarch64 (Jetson Nano). No issue found on amd64 or armv7.
rustc +nightly --version --verbose
:
rustc 1.63.0-nightly (490324f7b 2022-05-26)
binary: rustc
commit-hash: 490324f7b29d5f1a1e063a563045d790091ed639
commit-date: 2022-05-26
host: aarch64-unknown-linux-gnu
release: 1.63.0-nightly
LLVM version: 14.0.4
Same issue with both gcc and clang for the C code
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
Backtrace: N.A.
Metadata
Metadata
Assignees
Labels
Area: Concerning the application binary interface (ABI)Area: Code generationCategory: This is a bug.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessArmv8-A or later processors in AArch64 modeCritical priorityRelevant to the compiler team, which will review and decide on the PR/issue.