Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing casts in const macro translation #853

Open
DCNick3 opened this issue Feb 24, 2023 · 0 comments
Open

Missing casts in const macro translation #853

DCNick3 opened this issue Feb 24, 2023 · 0 comments
Labels
mistranslation Translating a well-behaved program changes its behavior

Comments

@DCNick3
Copy link

DCNick3 commented Feb 24, 2023

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

DCNick3 added a commit to DCNick3/unsafe-libopus that referenced this issue Feb 24, 2023
@fw-immunant fw-immunant added the mistranslation Translating a well-behaved program changes its behavior label Apr 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mistranslation Translating a well-behaved program changes its behavior
Projects
None yet
Development

No branches or pull requests

2 participants