From f8b49936bc97b5e7303f60c2e45f504249da31a2 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 27 Jun 2020 16:15:27 +0200 Subject: [PATCH 1/5] Various unix socket fixes (+socketpair!) --- src/header/sys_un/mod.rs | 9 ++++ src/platform/redox/epoll.rs | 10 ++-- src/platform/redox/socket.rs | 89 ++++++++++++++++++++++++++---------- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/header/sys_un/mod.rs b/src/header/sys_un/mod.rs index 6399f74bd2..b573889959 100644 --- a/src/header/sys_un/mod.rs +++ b/src/header/sys_un/mod.rs @@ -5,3 +5,12 @@ pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } + +impl sockaddr_un { + pub fn path_len(&self) -> usize { + let base = self as *const _ as usize; + let path = &self.sun_path as *const _ as usize; + trace!("base: {:#X}, path: {:#X}", base, path); + path - base + } +} diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs index 610a81063c..74b55d6655 100644 --- a/src/platform/redox/epoll.rs +++ b/src/platform/redox/epoll.rs @@ -29,9 +29,9 @@ impl PalEpoll for Sys { id: fd as usize, flags: syscall::EventFlags::from_bits(unsafe { (*event).events as usize }) .expect("epoll: invalid bit pattern"), - // NOTE: Danger when using non 64-bit systems. If this is - // needed, use a box or something - data: unsafe { mem::transmute((*event).data) }, + // NOTE: Danger when using something smaller than 64-bit + // systems. If this is needed, use a box or something + data: unsafe { (*event).data.u64 as usize }, }, ) as c_int } @@ -102,7 +102,7 @@ impl PalEpoll for Sys { if bytes_read == -1 { return -1; } - let read = bytes_read as usize / mem::size_of::(); + let read = bytes_read as usize / mem::size_of::(); let mut count = 0; for i in 0..read { @@ -117,7 +117,7 @@ impl PalEpoll for Sys { } *event_ptr = epoll_event { events: event.flags.bits() as _, - data: mem::transmute(event.data), + data: epoll_data { u64: event.data as u64, }, ..Default::default() }; count += 1; diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index ab26d3694d..60ecdcd629 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -32,13 +32,17 @@ macro_rules! bind_or_connect { 0 }}; ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{ - if ($address_len as usize) < mem::size_of::() { + if ($address_len as usize) < mem::size_of::() { errno = syscall::EINVAL; return -1; } let path = match (*$address).sa_family as c_int { AF_INET => { + if ($address_len as usize) != mem::size_of::() { + errno = syscall::EINVAL; + return -1; + } let data = &*($address as *const sockaddr_in); let addr = slice::from_raw_parts( &data.sin_addr.s_addr as *const _ as *const u8, @@ -58,9 +62,10 @@ macro_rules! bind_or_connect { }, AF_UNIX => { let data = &*($address as *const sockaddr_un); + trace!("address: {:p}, data: {:p}, data2: {:#X}", $address, data, data as *const _ as usize); let addr = slice::from_raw_parts( &data.sun_path as *const _ as *const u8, - mem::size_of_val(&data.sun_path), + $address_len as usize - data.path_len(), ); let path = format!( "{}", @@ -91,7 +96,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so let path = slice::from_raw_parts_mut( &mut data.sun_path as *mut _ as *mut u8, - mem::size_of_val(&data.sun_path), + data.path_len(), ); let len = cmp::min(path.len(), buf.len()); @@ -165,6 +170,19 @@ unsafe fn inner_get_name( Ok(0) } +fn socket_kind(mut kind: c_int) -> (c_int, usize) { + let mut flags = O_RDWR; + if kind & SOCK_NONBLOCK == SOCK_NONBLOCK { + kind &= !SOCK_NONBLOCK; + flags |= O_NONBLOCK; + } + if kind & SOCK_CLOEXEC == SOCK_CLOEXEC { + kind &= !SOCK_CLOEXEC; + flags |= O_CLOEXEC; + } + (kind, flags) +} + impl PalSocket for Sys { unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int { let stream = e(syscall::dup(socket as usize, b"listen")) as c_int; @@ -357,7 +375,7 @@ impl PalSocket for Sys { e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int } - unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int { + unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int { if domain != AF_INET && domain != AF_UNIX { errno = syscall::EAFNOSUPPORT; return -1; @@ -367,15 +385,7 @@ impl PalSocket for Sys { // return -1; // } - let mut flags = O_RDWR; - if kind & SOCK_NONBLOCK == SOCK_NONBLOCK { - kind &= !SOCK_NONBLOCK; - flags |= O_NONBLOCK; - } - if kind & SOCK_CLOEXEC == SOCK_CLOEXEC { - kind &= !SOCK_CLOEXEC; - flags |= O_CLOEXEC; - } + let (kind, flags) = socket_kind(kind); // The tcp: and udp: schemes allow using no path, // and later specifying one using `dup`. @@ -386,19 +396,52 @@ impl PalSocket for Sys { _ => { errno = syscall::EPROTONOSUPPORT; -1 - } + }, } } fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int { - eprintln!( - "socketpair({}, {}, {}, {:p})", - domain, - kind, - protocol, - sv.as_mut_ptr() - ); - unsafe { errno = syscall::ENOSYS }; - return -1; + let (kind, flags) = socket_kind(kind); + + match (domain, kind) { + (AF_UNIX, SOCK_STREAM) => { + let listener = e(syscall::open("chan:", flags | O_CREAT)); + if listener == !0 { + return -1; + } + + // For now, chan: lets connects be instant, and instead blocks + // on any I/O performed. So we don't need to mark this as + // nonblocking. + + let fd0 = e(syscall::dup(listener, b"connect")); + if fd0 == !0 { + let _ = syscall::close(listener); + return -1; + } + + let fd1 = e(syscall::dup(listener, b"listen")); + if fd1 == !0 { + let _ = syscall::close(fd0); + let _ = syscall::close(listener); + return -1; + } + + sv[0] = fd0 as c_int; + sv[1] = fd1 as c_int; + 0 + }, + _ => unsafe { + eprintln!( + "socketpair({}, {}, {}, {:p})", + domain, + kind, + protocol, + sv.as_mut_ptr() + ); + errno = syscall::EPROTONOSUPPORT; + -1 + }, + } } } From 593925ceb46583c75a4b541598937aad30d4a3d3 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 29 Jun 2020 11:34:51 +0200 Subject: [PATCH 2/5] Unambiguate all include guards GNU binutils also uses _FNMATCH_H for a guard, maybe along others! --- src/header/_aio/cbindgen.toml | 2 +- src/header/_fenv/cbindgen.toml | 2 +- src/header/_template/cbindgen.toml | 2 +- src/header/_wctype/cbindgen.toml | 2 +- src/header/assert/cbindgen.toml | 2 +- src/header/ctype/cbindgen.toml | 2 +- src/header/dirent/cbindgen.toml | 2 +- src/header/dlfcn/cbindgen.toml | 2 +- src/header/errno/cbindgen.toml | 2 +- src/header/fcntl/cbindgen.toml | 2 +- src/header/float/cbindgen.toml | 2 +- src/header/fnmatch/cbindgen.toml | 2 +- src/header/getopt/cbindgen.toml | 2 +- src/header/grp/cbindgen.toml | 2 +- src/header/inttypes/cbindgen.toml | 2 +- src/header/libgen/cbindgen.toml | 2 +- src/header/limits/cbindgen.toml | 2 +- src/header/locale/cbindgen.toml | 2 +- src/header/netdb/cbindgen.toml | 2 +- src/header/poll/cbindgen.toml | 2 +- src/header/pwd/cbindgen.toml | 2 +- src/header/regex/cbindgen.toml | 2 +- src/header/semaphore/cbindgen.toml | 2 +- src/header/sgtty/cbindgen.toml | 2 +- src/header/signal/cbindgen.toml | 2 +- src/header/stdio/cbindgen.toml | 2 +- src/header/stdlib/cbindgen.toml | 2 +- src/header/string/cbindgen.toml | 2 +- src/header/strings/cbindgen.toml | 2 +- src/header/termios/cbindgen.toml | 2 +- src/header/time/cbindgen.toml | 2 +- src/header/unistd/cbindgen.toml | 2 +- src/header/utime/cbindgen.toml | 2 +- src/header/wchar/cbindgen.toml | 2 +- src/header/wctype/cbindgen.toml | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/header/_aio/cbindgen.toml b/src/header/_aio/cbindgen.toml index f7e9c7085c..fd387cb50e 100644 --- a/src/header/_aio/cbindgen.toml +++ b/src/header/_aio/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_AIO_H" +include_guard = "_RELIBC_AIO_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/_fenv/cbindgen.toml b/src/header/_fenv/cbindgen.toml index dc3df6a78a..e8ca9b12ad 100644 --- a/src/header/_fenv/cbindgen.toml +++ b/src/header/_fenv/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdint.h", "sys/types.h"] -include_guard = "_FENV_H" +include_guard = "_RELIBC_FENV_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/_template/cbindgen.toml b/src/header/_template/cbindgen.toml index 6eb7533937..fbdebd78fd 100644 --- a/src/header/_template/cbindgen.toml +++ b/src/header/_template/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_TEMPLATE_H" +include_guard = "_RELIBC_TEMPLATE_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/_wctype/cbindgen.toml b/src/header/_wctype/cbindgen.toml index 57aab6a402..9477e2aa38 100644 --- a/src/header/_wctype/cbindgen.toml +++ b/src/header/_wctype/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_WCTYPE_H" +include_guard = "_RELIBC_WCTYPE_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/assert/cbindgen.toml b/src/header/assert/cbindgen.toml index eec2bfb141..7d1598f414 100644 --- a/src/header/assert/cbindgen.toml +++ b/src/header/assert/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["bits/assert.h"] -include_guard = "_ASSERT_H" +include_guard = "_RELIBC_ASSERT_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/ctype/cbindgen.toml b/src/header/ctype/cbindgen.toml index ff4f1d59d1..f47026b46c 100644 --- a/src/header/ctype/cbindgen.toml +++ b/src/header/ctype/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["bits/ctype.h"] -include_guard = "_CTYPE_H" +include_guard = "_RELIBC_CTYPE_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/dirent/cbindgen.toml b/src/header/dirent/cbindgen.toml index 252f91ffe9..5ba9d76a14 100644 --- a/src/header/dirent/cbindgen.toml +++ b/src/header/dirent/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/types.h"] -include_guard = "_DIRENT_H" +include_guard = "_RELIBC_DIRENT_H" language = "C" style = "Both" trailer = "#include " diff --git a/src/header/dlfcn/cbindgen.toml b/src/header/dlfcn/cbindgen.toml index 7e00f6ecdc..3a324bd8cb 100644 --- a/src/header/dlfcn/cbindgen.toml +++ b/src/header/dlfcn/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_DLFCN_H" +include_guard = "_RELIBC_DLFCN_H" language = "C" style = "Type" no_includes = true diff --git a/src/header/errno/cbindgen.toml b/src/header/errno/cbindgen.toml index 97769954d3..7de26bfdf8 100644 --- a/src/header/errno/cbindgen.toml +++ b/src/header/errno/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["bits/errno.h"] -include_guard = "_ERRNO_H" +include_guard = "_RELIBC_ERRNO_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/fcntl/cbindgen.toml b/src/header/fcntl/cbindgen.toml index 28019aeebb..40377c713a 100644 --- a/src/header/fcntl/cbindgen.toml +++ b/src/header/fcntl/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdarg.h", "sys/types.h"] -include_guard = "_FCNTL_H" +include_guard = "_RELIBC_FCNTL_H" trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/float/cbindgen.toml b/src/header/float/cbindgen.toml index 976cd7b879..4ca9cc2ea7 100644 --- a/src/header/float/cbindgen.toml +++ b/src/header/float/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/types.h", "bits/float.h"] -include_guard = "_FLOAT_H" +include_guard = "_RELIBC_FLOAT_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/fnmatch/cbindgen.toml b/src/header/fnmatch/cbindgen.toml index 1acf898cf0..c5cb5babab 100644 --- a/src/header/fnmatch/cbindgen.toml +++ b/src/header/fnmatch/cbindgen.toml @@ -1,4 +1,4 @@ -include_guard = "_FNMATCH_H" +include_guard = "_RELIBC_FNMATCH_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/getopt/cbindgen.toml b/src/header/getopt/cbindgen.toml index 3d74bd500e..36e260094b 100644 --- a/src/header/getopt/cbindgen.toml +++ b/src/header/getopt/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["unistd.h"] -include_guard = "_GETOPT_H" +include_guard = "_RELIBC_GETOPT_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/grp/cbindgen.toml b/src/header/grp/cbindgen.toml index 8db7bd7da2..4a2e9f2cf0 100644 --- a/src/header/grp/cbindgen.toml +++ b/src/header/grp/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_GRP_H" +include_guard = "_RELIBC_GRP_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/inttypes/cbindgen.toml b/src/header/inttypes/cbindgen.toml index 81e458051f..f923cb6804 100644 --- a/src/header/inttypes/cbindgen.toml +++ b/src/header/inttypes/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdint.h", "wchar.h"] -include_guard = "_INTTYPES_H" +include_guard = "_RELIBC_INTTYPES_H" trailer = "#include " language = "C" style = "Type" diff --git a/src/header/libgen/cbindgen.toml b/src/header/libgen/cbindgen.toml index b407f8cc16..50d050350e 100644 --- a/src/header/libgen/cbindgen.toml +++ b/src/header/libgen/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_LIBGEN_H" +include_guard = "_RELIBC_LIBGEN_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/limits/cbindgen.toml b/src/header/limits/cbindgen.toml index a35e1404eb..df8b0b0469 100644 --- a/src/header/limits/cbindgen.toml +++ b/src/header/limits/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_LIMITS_H" +include_guard = "_RELIBC_LIMITS_H" trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/locale/cbindgen.toml b/src/header/locale/cbindgen.toml index 2a7072bb21..edb2300b9c 100644 --- a/src/header/locale/cbindgen.toml +++ b/src/header/locale/cbindgen.toml @@ -1,4 +1,4 @@ -include_guard = "_LOCALE_H" +include_guard = "_RELIBC_LOCALE_H" trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/netdb/cbindgen.toml b/src/header/netdb/cbindgen.toml index fdbf6fa894..b4332479d2 100644 --- a/src/header/netdb/cbindgen.toml +++ b/src/header/netdb/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/socket.h", "netinet/in.h"] -include_guard = "_NETDB_H" +include_guard = "_RELIBC_NETDB_H" trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/poll/cbindgen.toml b/src/header/poll/cbindgen.toml index db04f56cee..ac981e6ad1 100644 --- a/src/header/poll/cbindgen.toml +++ b/src/header/poll/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_POLL_H" +include_guard = "_RELIBC_POLL_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/pwd/cbindgen.toml b/src/header/pwd/cbindgen.toml index bce631e414..55d0cdf99c 100644 --- a/src/header/pwd/cbindgen.toml +++ b/src/header/pwd/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "sys/types.h"] -include_guard = "_PWD_H" +include_guard = "_RELIBC_PWD_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/regex/cbindgen.toml b/src/header/regex/cbindgen.toml index 550385cdb2..78dfc8ee0d 100644 --- a/src/header/regex/cbindgen.toml +++ b/src/header/regex/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/types.h"] -include_guard = "_REGEX_H" +include_guard = "_RELIBC_REGEX_H" language = "C" style = "Type" no_includes = true diff --git a/src/header/semaphore/cbindgen.toml b/src/header/semaphore/cbindgen.toml index 8514bfba07..0c01194989 100644 --- a/src/header/semaphore/cbindgen.toml +++ b/src/header/semaphore/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_SEMAPHORE_H" +include_guard = "_RELIBC_SEMAPHORE_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/sgtty/cbindgen.toml b/src/header/sgtty/cbindgen.toml index f6f653d6f5..f566f920ee 100644 --- a/src/header/sgtty/cbindgen.toml +++ b/src/header/sgtty/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/ioctl.h"] -include_guard = "_SGTTY_H" +include_guard = "_RELIBC_SGTTY_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/signal/cbindgen.toml b/src/header/signal/cbindgen.toml index 73a7c9e417..46bbe11352 100644 --- a/src/header/signal/cbindgen.toml +++ b/src/header/signal/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdint.h", "sys/types.h"] -include_guard = "_SIGNAL_H" +include_guard = "_RELIBC_SIGNAL_H" trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/stdio/cbindgen.toml b/src/header/stdio/cbindgen.toml index 1be8edc855..633b449850 100644 --- a/src/header/stdio/cbindgen.toml +++ b/src/header/stdio/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h"] -include_guard = "_STDIO_H" +include_guard = "_RELIBC_STDIO_H" trailer = "#include " language = "C" style = "Type" diff --git a/src/header/stdlib/cbindgen.toml b/src/header/stdlib/cbindgen.toml index 1f21fbb5ce..7e9b9a8698 100644 --- a/src/header/stdlib/cbindgen.toml +++ b/src/header/stdlib/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "alloca.h"] -include_guard = "_STDLIB_H" +include_guard = "_RELIBC_STDLIB_H" trailer = "#include " language = "C" style = "Type" diff --git a/src/header/string/cbindgen.toml b/src/header/string/cbindgen.toml index bea34fa1bb..9cee2c5da5 100644 --- a/src/header/string/cbindgen.toml +++ b/src/header/string/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "stdint.h", "strings.h"] -include_guard = "_STRING_H" +include_guard = "_RELIBC_STRING_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/strings/cbindgen.toml b/src/header/strings/cbindgen.toml index 20fc84e0ae..2897bd5423 100644 --- a/src/header/strings/cbindgen.toml +++ b/src/header/strings/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "stdint.h"] -include_guard = "_STRINGS_H" +include_guard = "_RELIBC_STRINGS_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/termios/cbindgen.toml b/src/header/termios/cbindgen.toml index eafb3c12af..03a82a153a 100644 --- a/src/header/termios/cbindgen.toml +++ b/src/header/termios/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stdint.h"] -include_guard = "_TERMIOS_H" +include_guard = "_RELIBC_TERMIOS_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/time/cbindgen.toml b/src/header/time/cbindgen.toml index 61af8ce831..0b7e7399bd 100644 --- a/src/header/time/cbindgen.toml +++ b/src/header/time/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["sys/types.h", "stdint.h", "stddef.h"] -include_guard = "_TIME_H" +include_guard = "_RELIBC_TIME_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/unistd/cbindgen.toml b/src/header/unistd/cbindgen.toml index f8450e0c69..610d6d21fe 100644 --- a/src/header/unistd/cbindgen.toml +++ b/src/header/unistd/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "stdint.h", "sys/types.h"] -include_guard = "_UNISTD_H" +include_guard = "_RELIBC_UNISTD_H" trailer = "#include \n#include " language = "C" style = "Tag" diff --git a/src/header/utime/cbindgen.toml b/src/header/utime/cbindgen.toml index a415b33c4b..e4e125542a 100644 --- a/src/header/utime/cbindgen.toml +++ b/src/header/utime/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = [] -include_guard = "_UTIME_H" +include_guard = "_RELIBC_UTIME_H" language = "C" style = "Tag" no_includes = true diff --git a/src/header/wchar/cbindgen.toml b/src/header/wchar/cbindgen.toml index 853cfd27e3..1a2836a9e7 100644 --- a/src/header/wchar/cbindgen.toml +++ b/src/header/wchar/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ] -include_guard = "_WCHAR_H" +include_guard = "_RELIBC_WCHAR_H" header = "#include " language = "C" style = "Type" diff --git a/src/header/wctype/cbindgen.toml b/src/header/wctype/cbindgen.toml index 872e70e925..032cfcb0ab 100644 --- a/src/header/wctype/cbindgen.toml +++ b/src/header/wctype/cbindgen.toml @@ -1,5 +1,5 @@ sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ] -include_guard = "_WCTYPE_H" +include_guard = "_RELIBC_WCTYPE_H" header = "#include " language = "C" style = "Type" From 39ce623d2df545a6ebea65038e4882b2bbef08c1 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 29 Jun 2020 11:36:07 +0200 Subject: [PATCH 3/5] Fix bind/connect's AF_UNIX socket path... again I don't really know for sure what all these silly rules are, but I think I got it now... --- src/header/sys_un/mod.rs | 2 +- src/platform/redox/socket.rs | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/header/sys_un/mod.rs b/src/header/sys_un/mod.rs index b573889959..63d26c8ff7 100644 --- a/src/header/sys_un/mod.rs +++ b/src/header/sys_un/mod.rs @@ -7,7 +7,7 @@ pub struct sockaddr_un { } impl sockaddr_un { - pub fn path_len(&self) -> usize { + pub fn path_offset(&self) -> usize { let base = self as *const _ as usize; let path = &self.sun_path as *const _ as usize; trace!("base: {:#X}, path: {:#X}", base, path); diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index 60ecdcd629..c7e55088b7 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -9,6 +9,7 @@ use super::{ use crate::header::{ arpa_inet::inet_aton, netinet_in::{in_port_t, sockaddr_in, in_addr}, + string::strnlen, sys_socket::{constants::*, sa_family_t, sockaddr, socklen_t}, sys_time::timeval, sys_un::sockaddr_un, @@ -62,15 +63,32 @@ macro_rules! bind_or_connect { }, AF_UNIX => { let data = &*($address as *const sockaddr_un); - trace!("address: {:p}, data: {:p}, data2: {:#X}", $address, data, data as *const _ as usize); + + // NOTE: It's UB to access data in given address that exceeds + // the given address length. + + let maxlen = cmp::min( + // Max path length of the full-sized struct + data.sun_path.len(), + // Length inferred from given addrlen + $address_len as usize - data.path_offset() + ); + let len = cmp::min( + // The maximum length of the address + maxlen, + // The first NUL byte, if any + strnlen(&data.sun_path as *const _, maxlen as size_t), + ); + let addr = slice::from_raw_parts( &data.sun_path as *const _ as *const u8, - $address_len as usize - data.path_len(), + len, ); let path = format!( "{}", str::from_utf8(addr).unwrap() ); + trace!("path: {:?}", path); path }, @@ -96,7 +114,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so let path = slice::from_raw_parts_mut( &mut data.sun_path as *mut _ as *mut u8, - data.path_len(), + data.sun_path.len(), ); let len = cmp::min(path.len(), buf.len()); From 56e1eceb28be8663437039b4a787feddd4f4c802 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 29 Jun 2020 15:24:16 +0200 Subject: [PATCH 4/5] Replace AllocStringWriter with CVec --- src/c_vec.rs | 59 +++++++++++++++++++++++++++++++++++++---- src/header/stdio/mod.rs | 7 +++-- src/platform/mod.rs | 50 +++++----------------------------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/c_vec.rs b/src/c_vec.rs index 1a335cce02..fea7aeffff 100644 --- a/src/c_vec.rs +++ b/src/c_vec.rs @@ -1,6 +1,10 @@ -use crate::platform::{self, types::*}; +use crate::{ + io::{self, Write}, + platform::{self, WriteByte, types::*}, +}; use core::{ cmp, + fmt, iter::IntoIterator, mem, ops::{Deref, DerefMut}, @@ -67,6 +71,9 @@ impl CVec { start = start.add(1); } } + + // Push stuff + pub fn reserve(&mut self, required: usize) -> Result<(), AllocError> { let reserved_len = self .len @@ -82,8 +89,8 @@ impl CVec { Ok(()) } pub fn push(&mut self, elem: T) -> Result<(), AllocError> { + self.reserve(1)?; unsafe { - self.reserve(1)?; ptr::write(self.ptr.as_ptr().add(self.len), elem); } self.len += 1; // no need to bounds check, as new len <= cap @@ -93,21 +100,26 @@ impl CVec { where T: Copy, { + self.reserve(elems.len())?; unsafe { - self.reserve(elems.len())?; ptr::copy_nonoverlapping(elems.as_ptr(), self.ptr.as_ptr().add(self.len), elems.len()); } self.len += elems.len(); // no need to bounds check, as new len <= cap Ok(()) } pub fn append(&mut self, other: &mut Self) -> Result<(), AllocError> { + let len = other.len; + other.len = 0; // move + self.reserve(len)?; unsafe { - self.reserve(other.len())?; - ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), other.len()); + ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), len); } self.len += other.len(); // no need to bounds check, as new len <= cap Ok(()) } + + // Pop stuff + pub fn truncate(&mut self, len: usize) { if len < self.len { unsafe { @@ -126,6 +138,18 @@ impl CVec { } Ok(()) } + pub fn pop(&mut self) -> Option { + if self.is_empty() { + None + } else { + let elem = unsafe { ptr::read(self.as_ptr().add(self.len - 1)) }; + self.len -= 1; + Some(elem) + } + } + + // Misc stuff + pub fn capacity(&self) -> usize { self.cap } @@ -176,3 +200,28 @@ impl<'a, T> IntoIterator for &'a mut CVec { <&mut [T]>::into_iter(&mut *self) } } + +impl Write for CVec { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.extend_from_slice(buf).map_err(|err| io::Error::new( + io::ErrorKind::Other, + "AllocStringWriter::write failed to allocate", + ))?; + Ok(buf.len()) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} +impl fmt::Write for CVec { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.write(s.as_bytes()).map_err(|_| fmt::Error)?; + Ok(()) + } +} +impl WriteByte for CVec { + fn write_u8(&mut self, byte: u8) -> fmt::Result { + self.write(&[byte]).map_err(|_| fmt::Error)?; + Ok(()) + } +} diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 2b22cf4ac5..7693cd2157 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -16,6 +16,7 @@ use core::{ use crate::{ c_str::CStr, + c_vec::CVec, fs::File, header::{ errno::{self, STR_ERROR}, @@ -1021,9 +1022,11 @@ pub unsafe extern "C" fn vasprintf( format: *const c_char, ap: va_list, ) -> c_int { - let mut alloc_writer = platform::AllocStringWriter(ptr::null_mut(), 0); + let mut alloc_writer = CVec::new(); let ret = printf::printf(&mut alloc_writer, format, ap); - *strp = alloc_writer.0 as *mut c_char; + alloc_writer.push(0).unwrap(); + alloc_writer.shrink_to_fit().unwrap(); + *strp = alloc_writer.leak() as *mut c_char; ret } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 5b63f1a997..3978625e4f 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -104,45 +104,6 @@ impl Read for FileReader { } } -pub struct AllocStringWriter(pub *mut u8, pub usize); -impl Write for AllocStringWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - let ptr = unsafe { realloc(self.0 as *mut c_void, self.1 + buf.len() + 1) as *mut u8 }; - if ptr.is_null() { - return Err(io::Error::new( - io::ErrorKind::Other, - "AllocStringWriter::write failed to allocate", - )); - } - self.0 = ptr; - - unsafe { - ptr::copy_nonoverlapping(buf.as_ptr(), self.0.add(self.1), buf.len()); - self.1 += buf.len(); - *self.0.add(self.1) = 0; - } - - Ok(buf.len()) - } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} -impl fmt::Write for AllocStringWriter { - fn write_str(&mut self, s: &str) -> fmt::Result { - // can't fail - self.write(s.as_bytes()).unwrap(); - Ok(()) - } -} -impl WriteByte for AllocStringWriter { - fn write_u8(&mut self, byte: u8) -> fmt::Result { - // can't fail - self.write(&[byte]).unwrap(); - Ok(()) - } -} - pub struct StringWriter(pub *mut u8, pub usize); impl Write for StringWriter { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -155,11 +116,14 @@ impl Write for StringWriter { self.0 = self.0.add(copy_size); *self.0 = 0; } - - Ok(copy_size) - } else { - Ok(0) } + + // Pretend the entire slice was written. This is because many functions + // (like snprintf) expects a return value that reflects how many bytes + // *would have* been written. So keeping track of this information is + // good, and then if we want the *actual* written size we can just go + // `cmp::min(written, maxlen)`. + Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) From 29ad5b75c9d1940651a9643159fe79f2fd27a8c0 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 29 Jun 2020 21:03:29 +0200 Subject: [PATCH 5/5] Fix broken CVec Oops, forgot to initiate the pointer after uses of CVec::new() --- src/c_vec.rs | 70 +++++++++++++++++++++++++++--- tests/expected/stdio/printf.stdout | 4 ++ tests/stdio/printf.c | 12 +++++ tests/verify.sh | 1 - 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/c_vec.rs b/src/c_vec.rs index fea7aeffff..f1d1c0f936 100644 --- a/src/c_vec.rs +++ b/src/c_vec.rs @@ -57,8 +57,13 @@ impl CVec { } unsafe fn resize(&mut self, cap: usize) -> Result<(), AllocError> { let size = Self::check_mul(cap, mem::size_of::())?; - let ptr = NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T) - .ok_or(AllocError)?; + let ptr = if cap == 0 { + NonNull::dangling() + } else if self.cap > 0 { + NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T).ok_or(AllocError)? + } else { + NonNull::new((platform::alloc(size)) as *mut T).ok_or(AllocError)? + }; self.ptr = ptr; self.cap = cap; Ok(()) @@ -75,13 +80,13 @@ impl CVec { // Push stuff pub fn reserve(&mut self, required: usize) -> Result<(), AllocError> { - let reserved_len = self + let required_len = self .len .checked_add(required) .ok_or(AllocError) .and_then(Self::check_bounds)?; - let new_cap = cmp::min(reserved_len.next_power_of_two(), core::isize::MAX as usize); - if new_cap > self.cap { + if required_len > self.cap { + let new_cap = cmp::min(required_len.next_power_of_two(), core::isize::MAX as usize); unsafe { self.resize(new_cap)?; } @@ -225,3 +230,58 @@ impl WriteByte for CVec { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::CVec; + + #[test] + fn push_pop() { + let mut vec = CVec::new(); + vec.push(1).unwrap(); + vec.push(2).unwrap(); + vec.push(3).unwrap(); + assert_eq!(&vec[..], &[1, 2, 3]); + assert_eq!(vec.pop().unwrap(), 3); + assert_eq!(&vec[..], &[1, 2]); + } + #[test] + fn extend_from_slice() { + use core_io::Write; + + let mut vec = CVec::new(); + vec.extend_from_slice(&[1, 2, 3]).unwrap(); + vec.extend_from_slice(&[4, 5, 6]).unwrap(); + assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6]); + assert_eq!(vec.write(&[7, 8, 9]).unwrap(), 3); + assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8, 9]); + } + #[test] + fn dropped() { + use alloc::rc::Rc; + + let counter = Rc::new(()); + let mut vec = CVec::with_capacity(3).unwrap(); + vec.push(Rc::clone(&counter)).unwrap(); + vec.push(Rc::clone(&counter)).unwrap(); + vec.push(Rc::clone(&counter)).unwrap(); + assert_eq!(Rc::strong_count(&counter), 4); + + let popped = vec.pop().unwrap(); + assert_eq!(Rc::strong_count(&counter), 4); + drop(popped); + assert_eq!(Rc::strong_count(&counter), 3); + + vec.push(Rc::clone(&counter)).unwrap(); + vec.push(Rc::clone(&counter)).unwrap(); + vec.push(Rc::clone(&counter)).unwrap(); + + assert_eq!(vec.len(), 5); + assert_eq!(Rc::strong_count(&counter), 6); + vec.truncate(1); + assert_eq!(Rc::strong_count(&counter), 2); + + drop(vec); + assert_eq!(Rc::strong_count(&counter), 1); + } +} diff --git a/tests/expected/stdio/printf.stdout b/tests/expected/stdio/printf.stdout index ca878f7fa6..5683f0cad8 100644 --- a/tests/expected/stdio/printf.stdout +++ b/tests/expected/stdio/printf.stdout @@ -60,3 +60,7 @@ Non-finite float madness: %F: INF -INF NAN -NAN %g: inf -inf nan -nan %G: INF -INF NAN -NAN +Testing asprintf... +printed: test string, value: 11 +printed: test string 2, value: 13 +printed: test string 2, value: 13 diff --git a/tests/stdio/printf.c b/tests/stdio/printf.c index 6e05cad21c..c8fdafef67 100644 --- a/tests/stdio/printf.c +++ b/tests/stdio/printf.c @@ -74,4 +74,16 @@ int main(void) { } printf("\n"); } + + puts("Testing asprintf..."); + char *s = NULL; + int res = asprintf(&s, "test string"); + printf("printed: %s, value: %d\n", s, res); + free(s); + res = asprintf(&s, "test string %d", 2); + printf("printed: %s, value: %d\n", s, res); + free(s); + res = asprintf(&s, "test %s %d", "string", 2); + printf("printed: %s, value: %d\n", s, res); + free(s); } diff --git a/tests/verify.sh b/tests/verify.sh index 86438f8946..2f778e1a64 100755 --- a/tests/verify.sh +++ b/tests/verify.sh @@ -40,6 +40,5 @@ do if [ "${status}" != "0" ] then echo "# ${name}: failed with status ${status} #" - exit 1 fi done