ztmux 0.1.0

A Rust port of tmux — the full terminal multiplexer, server and client
Documentation
// Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#[cfg(target_os = "macos")]
/// C `vendor/tmux/compat/reallocarray.c:32`: `void *reallocarray(void *optr, size_t nmemb, size_t size)`
pub unsafe fn reallocarray(
    optr: *mut core::ffi::c_void,
    nmemb: usize,
    size: usize,
) -> *mut core::ffi::c_void {
    const MUL_NO_OVERFLOW: usize = 1usize << (size_of::<usize>() * 4);

    unsafe {
        if (nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW)
            && nmemb > 0
            && usize::MAX / nmemb < size
        {
            crate::errno!() = libc::ENOMEM;
            return core::ptr::null_mut();
        }
        libc::realloc(optr, size * nmemb)
    }
}

#[cfg(target_os = "linux")]
pub(crate) use libc::reallocarray;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_reallocarray_alloc_usable() {
        // 4 * 4 = 16 bytes: non-null and writable/readable.
        unsafe {
            let p = reallocarray(core::ptr::null_mut(), 4, 4).cast::<u8>();
            assert!(!p.is_null());
            for i in 0..16usize {
                *p.add(i) = i as u8;
            }
            for i in 0..16usize {
                assert_eq!(*p.add(i), i as u8);
            }
            libc::free(p.cast());
        }
    }

    #[test]
    fn test_reallocarray_overflow_returns_null() {
        // nmemb * size overflows usize -> ENOMEM, null pointer.
        unsafe {
            let p = reallocarray(core::ptr::null_mut(), usize::MAX, 2);
            assert!(p.is_null());
        }
    }
}