Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create and pass a null-terminated array of C-strings (char**) in rust?

Tags:

arrays

rust

c-str

I'm playing around with a new init system with #![no_std] and extern crate rlibc and making syscalls with asm, and currently trying to not allocate memory either. So the scope of possible tools I have is limited.

I need to call the execve syscall, and it requires a char** argv, and a char **envp. I can hack together c-style strings as arrays of bytes with zeros, but how can I null-terminate a statically declared list of such (the last pointer being NULL)?

like image 725
Ant Manelope Avatar asked Jul 26 '14 08:07

Ant Manelope


People also ask

How do you null terminate a string in C?

The null terminated strings are basically a sequence of characters, and the last element is one null character (denoted by '\0'). When we write some string using double quotes (“…”), then it is converted into null terminated strings by the compiler.

Is a char array null-terminated in C?

A C-style string is a null (denoted by \0 ) terminated char array. The null occurs after the last character of the string. For an initialization using double quotes, "...", the compiler will insert the null .

Is rust string null-terminated?

Most C APIs require that the string being passed to them is null-terminated, and by default rust's string types are not null terminated. The other problem with translating Rust strings to C strings is that Rust strings can validly contain a null-byte in the middle of the string (0 is a valid Unicode codepoint).

Does char array include null-terminated?

Short answer: a null terminated string is a char array with a null value (0x00) after the last valid character in the string. Long Answer: It's important to remember that not every C and C++ compiler will initialize values for you.


1 Answers

After sleeping on this, I woke up with the answer, and it seems obvious to me now. Use slices of integers and set the last one to 0.

// Execute something as an example:
let filename: &[u8] = b"/usr/bin/sensors\x00";     // <-- Make c strings like this
let argv1: &[u8] = b"/usr/bin/sensors\x00";
let argv2: &[u8] = b"-h\x00";
let argv: &[int] = [                               // <-- store them in this
    ::core::intrinsics::transmute(argv1.as_ptr()), // <-- transmuting 
    ::core::intrinsics::transmute(argv2.as_ptr()),
    0                                              // <-- and NULL terminate
];
let envp: &[int] = [0];

::linux64::execve(filename,argv,envp);
like image 74
Ant Manelope Avatar answered Oct 23 '22 05:10

Ant Manelope