Skip to content

Missing casts in const macro translation #853

@DCNick3

Description

@DCNick3

A bug I found when working on unsafe-libopus

Apparently, when const macro translation is enabled, some casts are dropped, which leads to a change in semantics.

Reproducible case

#include <stdio.h>

#define silk_int16_MIN ((short)0x8000)

int test() { return silk_int16_MIN; }

int main() {
    printf("%d\n", test());
}

Without --translate-const-macros:

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
extern "C" {
    fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
}
#[no_mangle]
pub unsafe extern "C" fn test() -> libc::c_int {
    return 0x8000 as libc::c_int as libc::c_short as libc::c_int;
}
unsafe fn main_0() -> libc::c_int {
    printf(b"%d\n\0" as *const u8 as *const libc::c_char, test());
    return 0;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Outputs -32768

With --translate-const-macros:

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
extern "C" {
    fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
}
pub const silk_int16_MIN: libc::c_int = 0x8000 as libc::c_int;
#[no_mangle]
pub unsafe extern "C" fn test() -> libc::c_int {
    return silk_int16_MIN;
}
unsafe fn main_0() -> libc::c_int {
    printf(b"%d\n\0" as *const u8 as *const libc::c_char, test());
    return 0;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Outputs 32768

The bug

When no constants are generated the value is correctly cast to c_short before being widened back: 0x8000 as libc::c_int as libc::c_short as libc::c_int

When constant translation is enabled, however, the 0x8000 constant is not cast to the short type and stored directly as an int, which is incorrect

Metadata

Metadata

Assignees

No one assigned

    Labels

    mistranslationTranslating a well-behaved program changes its behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions