Description
It is unsafe to convert every &[u8]
into a &str
, because &str
s need to have a valid byte after the end of the characters. This means that this pattern:
let v = &['a' as u8, 'b' as u8, 'c' as u8];
let s = str::from_bytes_slice(v);
str::as_c_str(s, |ptr| call_c_function(ptr));
is unsafe because str::as_c_str
dereferences the next byte past the end of the slice. This is safe when working with a ~str
as a &str
, because it has the trailing null. To do this safely, you need to copy the bytes:
let v = &['a' as u8, 'b' as u8, 'c' as u8];
let s = str::from_bytes(v);
str::as_c_str(s, |ptr| call_c_function(ptr));
While we could work around this by marking from_bytes_slice
as unsafe and documenting this unsafe behavior, it would be simplest to just remove the trailing null from strings and allow the end user to add the trailing null if they want it. .as_c_str()
can still take the fast path if the string is null terminated, or allocate a temporary string otherwise.
Some comments from the IRC discussion:
@graydon suggests renaming .as_c_str()
to .as_null_terminated_c_str()
@cmr suggested .as_null_terminated_str()
@bstrie suggested .null_terminate()
@Kimundi mentioned a .as_c_str()
that takes a &mut ~str
, adds a NULL, calls the closure, then removes the NULL before exiting.
cc: #6869