From 7c545b4b9c31dbfb2e8430aded030654a92e967a Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 28 Feb 2026 19:17:45 +0100 Subject: First commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libabort.h | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 libabort.h (limited to 'libabort.h') diff --git a/libabort.h b/libabort.h new file mode 100644 index 0000000..333edb3 --- /dev/null +++ b/libabort.h @@ -0,0 +1,233 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBABORT_H +#define LIBABORT_H + +#include +#include +#include +#include +#include + + +#if defined(__GNUC__) +# if defined(__clang__) +# define LIBABORT_PRINTF__(FMT, ARGS) __attribute__((__format__(__printf__, FMT, ARGS))) +# else +# define LIBABORT_PRINTF__(FMT, ARGS) __attribute__((__format__(__gnu_printf__, FMT, ARGS))) +# endif +# define LIBABORT_NONNULL__(INDEX) __attribute__((__nonnull__(INDEX))) +# define LIBABORT_ALL_NONNULL__ __attribute__((__nonnull__)) +# define LIBABORT_PURE__ __attribute__((__pure__)) +#else +# define LIBABORT_PRINTF__(FMT, ARGS) +# define LIBABORT_NONNULL__(INDEX) +# define LIBABORT_ALL_NONNULL__ +# define LIBABORT_PURE__ +#endif + + +#ifndef LIBABORT_NO_SHORTHANDS +# ifndef stracpy +# define stracpy libabort_stracpy +# endif +# ifndef saprintf +# define saprintf libabort_saprintf +# endif +# ifndef vsaprintf +# define vsaprintf libabort_vsaprintf +# endif +# ifndef stpacpy +# define stpacpy libabort_stpacpy +# endif +# ifndef stracat +# define stracat libabort_stracat +# endif +# ifndef stralen +# define stralen libabort_stralen +# endif +# ifndef stpacat +# define stpacat libabort_stpacat +# endif +#endif + + +/** + * libabort_stracpy + * + * Copy a string like strncpy(3), but abort if truncation would occur + * + * @param dst The destination buffer + * @param src The source string + * @param size The size of `dst`, in bytes + * @return `dst` + */ +LIBABORT_ALL_NONNULL__ +inline char * +libabort_stracpy(char *dst, const char *src, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + if ((dst[i] = src[i]) == '\0') + return dst; + abort(); +} + + +/** + * libabort_stpacpy + * + * Copy a string like stpcpy(3), but abort if truncation would occur. + * + * @param dst The destination buffer + * @param src The source string + * @param size The size of `dst`, in bytes + * @return A pointer to the terminating NUL byte in `dst` + */ +LIBABORT_ALL_NONNULL__ +inline char * +libabort_stpacpy(char *dst, const char *src, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + if ((dst[i] = src[i]) == '\0') + return &dst[i]; + abort(); +} + + +/** + * libabort_stracat + * + * Concatenate strings like strcat(3), but abort if truncation would occur. + * + * @param dst The destination buffer (must contain a NUL-terminated string) + * @param src The source string + * @param size The size of `dst`, in bytes + * @return `dst` + */ +LIBABORT_ALL_NONNULL__ +inline char * +libabort_stracat(char *dst, const char *src, size_t size) +{ + size_t i, j; + for (i = 0; i < size; i++) + if (dst[i] == '\0') + break; + if (i == size) + abort(); + for (j = 0; i < size; i++, j++) + if ((dst[i] = src[j]) == '\0') + return dst; + abort(); +} + + +/** + * libabort_stralen + * + * Get the length of a string like strlen(3), but abort if no NUL byte is found + * within `size` bytes. + * + * @param str The string + * @param size The maximum number of bytes to examine + * @return The length of the string, excluding the terminating NUL byte + */ +LIBABORT_PURE__ +LIBABORT_ALL_NONNULL__ +inline size_t +libabort_stralen(const char *str, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + if (!str[i]) + return i; + abort(); +} + + +/** + * libabort_stpacat + * + * Concatenate strings like stpcat(3) would (non-standard), but abort if + * truncation would occur. + * + * @param dst The destination buffer (must contain a NUL-terminated string) + * @param src The source string + * @param size The size of `dst`, in bytes + * @return A pointer to the terminating NUL byte in `dst` + */ +LIBABORT_ALL_NONNULL__ +inline char * +libabort_stpacat(char *dst, const char *src, size_t size) +{ + size_t i, j; + for (i = 0; i < size; i++) + if (dst[i] == '\0') + break; + if (i == size) + abort(); + for (j = 0; i < size; i++, j++) + if ((dst[i] = src[j]) == '\0') + return &dst[i]; + abort(); +} + + +/** + * libabort_vsaprintf + * + * Format a string like vsnprintf(3), but abort if truncation would occur + * + * @param buf The output buffer + * @param size The size of `buf`, in bytes + * @param fmt The format string + * @param ap The format arguments + * @return The number of bytes written excluding the terminating NUL byte + * + * NB! This function aborts if `size` is 0, use vsnprintf(3) get the size required for `buf` + */ +LIBABORT_NONNULL__(1) +LIBABORT_NONNULL__(3) +LIBABORT_PRINTF__(3, 0) +inline int +libabort_vsaprintf(char *buf, size_t size, const char *fmt, va_list ap) +{ + int n = vsnprintf(buf, size, fmt, ap); + if (n < 0 || (size_t)n >= size) + abort(); + return n; +} + + +/** + * libabort_saprintf + * + * Format a string like snprintf(3), but abort if truncation would occur + * + * @param buf The output buffer + * @param size The size of `buf`, in bytes + * @param fmt The format string + * @return The number of bytes written excluding the terminating NUL byte + * + * NB! This function aborts if `size` is 0, use snprintf(3) get the size required for `buf` + */ +LIBABORT_NONNULL__(1) +LIBABORT_NONNULL__(3) +LIBABORT_PRINTF__(3, 4) +inline int +libabort_saprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list ap; + int r; + va_start(ap, fmt); + r = libabort_vsaprintf(buf, size, fmt, ap); + va_end(ap); + return r; +} + + +#undef LIBABORT_PRINTF__ +#undef LIBABORT_NONNULL__ +#undef LIBABORT_ALL_NONNULL__ + +#endif -- cgit v1.2.3-70-g09d2