-
Notifications
You must be signed in to change notification settings - Fork 15
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool!
} as *mut libc::c_char, | ||
if buf_len == 0 { fakebuf.len() } else { buf_len }, | ||
) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix for the zero-length readlink buffer in bytecodealliance/lucet#213 looks a little simpler; would it make sense to do the same thing here? That said, I do like the comment here about investigating having nix
take care of this detail transparently, so please preserve that comment in any case :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, do you know if they've double checked it for this particular use case? I'm asking because actually, I've already tried something similar before, but due to the way nix::fcntl::readlinkat
is implemented, it wouldn't work for me. Perhaps I was doing something wrong. But to elaborate, here's the readlinkat
impl taken verbatim from the nix
crate (here's the link):
pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
let res = path.with_nix_path(|cstr| {
unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
})?;
wrap_readlink_result(buffer, res)
}
And in turn wrap_readlink_result
does the following:
fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
match Errno::result(res) {
Err(err) => Err(err),
Ok(len) => {
if (len as usize) >= buffer.len() {
Err(Error::Sys(Errno::ENAMETOOLONG))
} else {
Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
}
}
}
}
Due to the wrap_readlink_result
, if we ever try to read link that's longer than the buffer we provide, nix
will trip with ENAMETOOLONG
which is exactly the error I was getting when trying the same approach as bytecodealliance/lucet#213 for zero-length buffer.
@jedisct1, @sunfishcode any thoughts and help on this will be much appreciated! :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the comment above, when I said "it wouldn't work for me" I meant that bytecodealliance/lucet#213 approach wouldn't pass the test_readlink_no_buffer
test in sunfishcode/misc-tests. As I pointed out above, this is due to the fact that, the nix
crate doesn't only wrap libc::readlinkat
syscall but actually checks whether the passed in buffer is larger than the actual number of bytes written to the buffer. So, even if we pass in a buffer of length 1, due to the above additional check, I believe that nix::fcntl::readlinkat
will always return ENAMETOOLONG
for that particular case.
Ok, the PR here looks good to me. I'm going to file a separate issue about |
I've now filed https://github.com/CraneStation/wasi-common/issues/30. |
Nice one, thanks! |
This PR builds upon #26. It patches up all problems that cause sunfishcode/misc-tests to fail.
Summary of fixes:
fd_renumber
should currently fail when trying to renumber a preopenpath_readlink
should be able to handle 0-sized buffer (as pointed out by @sunfishcode in the original C impl, Linux requires the input buffer to have positive size, however, POSIX does not enforce that)path_open
had theOFlag
s the other way around: theelse
branch when determining read/write attributes should haveOFlags::O_RDONLY
as a fallthrough and notOFlags::O_WRONLY
as it was until nowpath_get
now correctly handles "interesting paths" with a plethora of trailing slashes, "..", etc. To achieve this, instead of iterating over raw paths (using bytes), we usestd::path::Components
functionality instead; it is still necessary to preserver the path's trailing slash so that opening a file as a dir fails as expectedpath_get
now correctly fails withEILSEQ
in the presence of spurious NULs in the input pathfd
encoding bytecodealliance/wasmtime#173 topath_open
path_open
to do with setting theneeded_base
flags in the presence ofOFlag::O_TRUNC
: up to now we were incorrectly adjustingneeded_inheriting
flags instead ofneeded_base
path_unlink_file
now correctly handles non-Linux *nix OSes, i.e.,unlinkat
may returnEPERM
on non-Linux host and it should be adjusted toEISDIR