taproot-c-scape 0.22.4

A libc bottom-half implementation in Rust (c-scape fork for the taproot libc)
Documentation
//! `__*_chk` functions.

use libc::{c_char, c_int, c_void, size_t};

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---chk-fail-1.html>
#[cold]
#[no_mangle]
unsafe extern "C" fn __chk_fail() -> ! {
    rustix::io::write(
        rustix::stdio::stderr(),
        b"A buffer overflow has been detected.\n",
    )
    .ok();
    libc::abort();
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---strcpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __strcpy_chk(
    dest: *mut c_char,
    src: *const c_char,
    destlen: size_t,
) -> *mut c_char {
    let src_strlen = libc::strlen(src);

    if src_strlen >= destlen {
        __chk_fail();
    }

    libc::memcpy(dest.cast(), src.cast(), src_strlen + 1).cast()
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---stpcpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __stpcpy_chk(
    dest: *mut c_char,
    src: *const c_char,
    destlen: size_t,
) -> *mut c_char {
    let src_strlen = libc::strlen(src);

    if src_strlen >= destlen {
        __chk_fail();
    }

    libc::memcpy(dest.cast(), src.cast(), src_strlen + 1);
    dest.add(src_strlen)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---memcpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __memcpy_chk(
    dest: *mut c_void,
    src: *const c_void,
    len: size_t,
    destlen: size_t,
) -> *mut c_void {
    if destlen < len {
        __chk_fail();
    }

    libc::memcpy(dest, src, len)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---memmove-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __memmove_chk(
    dest: *mut c_void,
    src: *const c_void,
    len: size_t,
    destlen: size_t,
) -> *mut c_void {
    if destlen < len {
        __chk_fail();
    }

    libc::memmove(dest, src, len)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---memset-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __memset_chk(
    dest: *mut c_void,
    c: c_int,
    len: size_t,
    destlen: size_t,
) -> *mut c_void {
    if destlen < len {
        __chk_fail();
    }

    libc::memset(dest, c, len)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---strcat-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __strcat_chk(
    dest: *mut c_char,
    src: *const c_char,
    destlen: size_t,
) -> *mut c_char {
    let dest_strlen = libc::strlen(dest);
    let src_strlen = libc::strlen(src);

    if let Some(sum) = dest_strlen.checked_add(src_strlen) {
        if let Some(sum) = sum.checked_add(1) {
            if sum <= destlen {
                return libc::strcat(dest, src);
            }
        }
    }

    __chk_fail()
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---strncpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __strncpy_chk(
    dest: *mut c_char,
    src: *const c_char,
    len: size_t,
    destlen: size_t,
) -> *mut c_char {
    if destlen < len {
        __chk_fail();
    }

    libc::strncpy(dest, src, len)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---strncat-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __strncat_chk(
    dest: *mut c_char,
    src: *const c_char,
    len: size_t,
    destlen: size_t,
) -> *mut c_char {
    if destlen < len {
        __chk_fail();
    }

    libc::strncat(dest, src, len)
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---fgets-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __fgets_chk(
    s: *mut c_char,
    size: size_t,
    strsize: c_int,
    stream: *mut c_void,
) -> *mut c_char {
    if strsize < 0 {
        __chk_fail();
    }
    if strsize as size_t > size {
        __chk_fail();
    }

    libc::fgets(s, strsize, stream.cast())
}

// <https://man7.org/linux/man-pages/man3/explicit_bzero.3.html>, the
// fortified form; volatile writes so the zeroing never optimizes away
#[no_mangle]
unsafe extern "C" fn __explicit_bzero_chk(dest: *mut c_void, len: size_t, destlen: size_t) {
    if len > destlen {
        __chk_fail();
    }
    let p = dest.cast::<u8>();
    for i in 0..len {
        p.add(i).write_volatile(0);
    }
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---mempcpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __mempcpy_chk(
    dest: *mut c_void,
    src: *const c_void,
    len: size_t,
    destlen: size_t,
) -> *mut c_void {
    if len > destlen {
        __chk_fail();
    }
    libc::memcpy(dest, src, len).cast::<u8>().add(len).cast()
}

// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---stpncpy-chk-1.html>
#[no_mangle]
unsafe extern "C" fn __stpncpy_chk(
    dest: *mut c_char,
    src: *const c_char,
    n: size_t,
    destlen: size_t,
) -> *mut c_char {
    if n > destlen {
        __chk_fail();
    }
    let mut copied = 0;
    while copied < n {
        let b = *src.add(copied);
        *dest.add(copied) = b;
        if b == 0 {
            break;
        }
        copied += 1;
    }
    for i in copied..n {
        *dest.add(i) = 0;
    }
    dest.add(copied)
}