From: Tobias Stoeckmann Date: Wed, 10 Jun 2026 17:56:40 +0000 (+0200) Subject: Add archive_integer.h X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16be3385236bb37bb3a2b6f9fa80aac98fd12e78;p=thirdparty%2Flibarchive.git Add archive_integer.h The archive_integer.h header offers various integer operations to libarchive, utilizing system functionality where possible. Signed-off-by: Tobias Stoeckmann --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 319679f75..37697c25f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -774,6 +774,7 @@ CHECK_C_SOURCE_COMPILES("#include #include int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) +LA_CHECK_INCLUDE_FILE("intsafe.h" HAVE_INTSAFE_H) LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H) @@ -788,6 +789,7 @@ LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) +LA_CHECK_INCLUDE_FILE("stdckdint.h" HAVE_STDCKDINT_H) LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) LA_CHECK_INCLUDE_FILE("stdio.h" HAVE_STDIO_H) LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) diff --git a/Makefile.am b/Makefile.am index fef62d416..250be4059 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,6 +114,7 @@ noinst_HEADERS= \ libarchive/archive_entry_locale.h \ libarchive/archive_entry_private.h \ libarchive/archive_hmac_private.h \ + libarchive/archive_integer.h \ libarchive/archive_openssl_evp_private.h \ libarchive/archive_openssl_hmac_private.h \ libarchive/archive_options_private.h \ diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 97ff59476..a082e6298 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -684,6 +684,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ICONV_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTSAFE_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 @@ -1025,6 +1028,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDARG_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDCKDINT_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 diff --git a/configure.ac b/configure.ac index 64683896d..543db407c 100644 --- a/configure.ac +++ b/configure.ac @@ -365,9 +365,9 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes], [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1], [Define to 1 if you have a working FS_IOC_GETFLAGS])]) -AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h]) -AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h]) -AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h]) +AC_CHECK_HEADERS([intsafe.h locale.h membership.h paths.h poll.h pthread.h]) +AC_CHECK_HEADERS([pwd.h readpassphrase.h signal.h spawn.h]) +AC_CHECK_HEADERS([stdarg.h stdckdint.h stdint.h stdlib.h string.h]) AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h]) AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h]) AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h]) diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 4fb917132..b29663742 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -40,6 +40,7 @@ SET(libarchive_SOURCES archive_entry_xattr.c archive_hmac.c archive_hmac_private.h + archive_integer.h archive_match.c archive_openssl_evp_private.h archive_openssl_hmac_private.h diff --git a/libarchive/archive_integer.h b/libarchive/archive_integer.h new file mode 100644 index 000000000..f0358b820 --- /dev/null +++ b/libarchive/archive_integer.h @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ARCHIVE_INTEGER_H_INCLUDED +#define ARCHIVE_INTEGER_H_INCLUDED + +#include "archive_platform.h" + +/* Note: This is a purely internal header! */ +/* Do not use this outside of libarchive internal code! */ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#ifdef HAVE_INTSAFE_H +#define ENABLE_INTSAFE_SIGNED_FUNCTIONS +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDCKDINT_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifdef HAVE_STDCKDINT_H +#define USE_STDCKDINT 1 +#elif (__GNUC__ >= 5 && !defined(__INTEL_COMPILER)) +#define USE_BUILTIN 1 +#elif __has_builtin(__builtin_add_overflow) +#define USE_BUILTIN 1 +#elif defined HAVE_INTSAFE_H +#define USE_INTSAFE 1 +#endif + +/* + * Disabling inline keyword for compilers known to choke on it: + * - Watcom C++ in C code. (For any version?) + * - SGI MIPSpro + * - Microsoft Visual C++ 6.0 (supposedly newer versions too) + * - IBM VisualAge 6 (XL v6) + * - Sun WorkShop C (SunPro) before 5.9 + */ +#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__) +#define inline +#elif defined(__IBMC__) && __IBMC__ < 700 +#define inline +#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590 +#define inline +#elif defined(_MSC_VER) || defined(__osf__) +#define inline __inline +#endif + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongAdd(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a > INT64_MAX - b) || + (b < 0 && a < INT64_MIN - b)) + return 1; + + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongAdd(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (a > UINT64_MAX - b) + return 1; + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongMult(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((a > 0 && b > 0 && a > INT64_MAX / b) || + (a < 0 && b > 0 && a < INT64_MIN / b) || + (a > 0 && b < 0 && b < INT64_MIN / a) || + (a < 0 && b < 0 && a < INT64_MAX / b)) + return 1; + + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongMult(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (b != 0 && a > UINT64_MAX / b) + return 1; + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_sub_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_sub(result, a, b); +#elif USE_BUILTIN + return __builtin_sub_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongSub(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a < INT64_MIN + b) || + (b < 0 && a > INT64_MAX + b)) + return 1; + + *result = a - b; + return 0; +#endif +} + +#endif