Iterating a slice of *const c_char corruptioin

Hello

I came across a strange behavior which surprised me. Using the iterator api of a slice of *const c_char causes some memory corruption. The context is handling program arguments in a no_std program:

#![no_std]
#![no_main]

use core::ffi::*;

extern "C" {
    pub fn printf(fmt: *const c_char, ...) -> c_int;
}

#[no_mangle]
pub extern "C" fn main(argc: c_int, argv: *const *const c_char) -> c_int {
    unsafe {
        let args = core::slice::from_raw_parts(argv, argc as _);
        for i in 0..argc { // this works
            printf("%s\n\0".as_ptr() as _, args[i as usize]); 
        }
        for arg in args {  // corruption here
            printf("%s\n\0".as_ptr() as _, arg);
        }
    }
    0
}

#[panic_handler]
fn ph(_: &core::panic::PanicInfo) -> ! {
    loop {}
}

Is it a bug in the code above? Or are my assumptions wrong?

P.S. To build you need to change your Cargo.toml:

[profile.dev]
panic = "abort"
# similarly change profile.release

And you might need to link libc in a build.rs file depending on your rust version:

fn main() {
    println!("cargo:rustc-link-lib=c");
}

I believe arg is a reference to the slice element containing the C pointer, so you need to pass *arg to pass the C pointer.

1 Like

Yes indeed, dereferencing arg fixes the issue.
Thank you

1 Like