Skip to content

Wrong cast of u16 to usize on aarch64 #97463

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

A-ABIArea: Concerning the application binary interface (ABI)A-codegenArea: Code generationC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-AArch64Armv8-A or later processors in AArch64 modeP-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions