From 0ee1a5f4b02c0e1e6c172b67192bb056c395b2fa Mon Sep 17 00:00:00 2001 From: mxms Date: Tue, 21 Oct 2025 04:03:27 +0000 Subject: [PATCH] Move non-abi breaking annotations into types.h By moving non-abi breaking annotations into types.h, this enables us to mark more of libwebp as unsafe to allow better interop with struct members which default to __single. Change-Id: I54b78f68581e41389538f7332989c04c2e02ccc7 Bug: webp:432511225 --- src/utils/bounds_safety.h | 69 ++----------------------------- src/webp/types.h | 86 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 66 deletions(-) diff --git a/src/utils/bounds_safety.h b/src/utils/bounds_safety.h index 51844d0b..d6104557 100644 --- a/src/utils/bounds_safety.h +++ b/src/utils/bounds_safety.h @@ -12,8 +12,10 @@ #ifndef WEBP_UTILS_BOUNDS_SAFETY_H_ #define WEBP_UTILS_BOUNDS_SAFETY_H_ -#include // For memcpy and friends +#ifdef WEBP_SUPPORT_FBOUNDS_SAFETY +#include +// // There's some inherent complexity here due to the way -fbounds-safety works. // Some annotations (notably __indexable and __bidi_indexable) change the ABI // of the function or struct, so we don't want those annotations to silently @@ -36,22 +38,6 @@ // have CMake append to a header file (like this one) that libwebp was built // with -fbounds-safety, so that we know to never make annotations vanish. -#ifdef WEBP_SUPPORT_FBOUNDS_SAFETY - -#include - -#define WEBP_ASSUME_UNSAFE_INDEXABLE_ABI \ - __ptrcheck_abi_assume_unsafe_indexable() - -#define WEBP_COUNTED_BY(x) __counted_by(x) -#define WEBP_COUNTED_BY_OR_NULL(x) __counted_by_or_null(x) -#define WEBP_SIZED_BY(x) __sized_by(x) -#define WEBP_SIZED_BY_OR_NULL(x) __sized_by_or_null(x) -#define WEBP_ENDED_BY(x) __ended_by(x) - -#define WEBP_UNSAFE_INDEXABLE __unsafe_indexable -#define WEBP_SINGLE __single - // The annotations below are ABI breaking as they turn normal pointers into // "wide" pointers. Breaking them down: // * __indexable is akin to { ptr_curr, ptr_end }, and can only be @@ -64,60 +50,11 @@ #define WEBP_INDEXABLE __indexable #define WEBP_BIDI_INDEXABLE __bidi_indexable -#define WEBP_UNSAFE_FORGE_SINGLE(typ, ptr) __unsafe_forge_single(typ, ptr) - -#define WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(typ, ptr, size) \ - __unsafe_forge_bidi_indexable(typ, ptr, size) - -// Provide memcpy/memset/memmove wrappers to make migration easier. -#define WEBP_UNSAFE_MEMCPY(dst, src, size) \ - do { \ - memcpy(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), \ - WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, src, size), size); \ - } while (0) - -#define WEBP_UNSAFE_MEMSET(dst, c, size) \ - do { \ - memset(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), c, size); \ - } while (0) - -#define WEBP_UNSAFE_MEMMOVE(dst, src, size) \ - do { \ - memmove(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), \ - WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, src, size), size); \ - } while (0) - -#define WEBP_UNSAFE_MEMCMP(s1, s2, size) \ - memcmp(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, s1, size), \ - WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, s2, size), size) - #else // WEBP_SUPPORT_FBOUNDS_SAFETY -#define WEBP_ASSUME_UNSAFE_INDEXABLE_ABI - -#define WEBP_COUNTED_BY(x) -#define WEBP_COUNTED_BY_OR_NULL(x) -#define WEBP_SIZED_BY(x) -#define WEBP_SIZED_BY_OR_NULL(x) -#define WEBP_ENDED_BY(x) - -#define WEBP_UNSAFE_INDEXABLE -#define WEBP_SINGLE #define WEBP_INDEXABLE #define WEBP_BIDI_INDEXABLE -#define WEBP_UNSAFE_MEMCPY(dst, src, size) memcpy(dst, src, size) -#define WEBP_UNSAFE_MEMSET(dst, c, size) memset(dst, c, size) -#define WEBP_UNSAFE_MEMMOVE(dst, src, size) memmove(dst, src, size) -#define WEBP_UNSAFE_MEMCMP(s1, s2, size) memcmp(s1, s2, size) - -#define WEBP_UNSAFE_FORGE_SINGLE(typ, ptr) ((typ)(ptr)) -#define WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(typ, ptr, size) ((typ)(ptr)) - #endif // WEBP_SUPPORT_FBOUNDS_SAFETY -// This macro exists to indicate intentionality with self-assignments and -// silence -Wself-assign compiler warnings. -#define WEBP_SELF_ASSIGN(x) x = x - #endif // WEBP_UTILS_BOUNDS_SAFETY_H_ diff --git a/src/webp/types.h b/src/webp/types.h index ab0c32aa..9521c863 100644 --- a/src/webp/types.h +++ b/src/webp/types.h @@ -90,4 +90,90 @@ WEBP_EXTERN void WebPFree(void* ptr); } // extern "C" #endif +#include // For memcpy and friends + +#ifdef WEBP_SUPPORT_FBOUNDS_SAFETY + +// As explained in src/utils/bounds_safety.h, the below macros are defined +// somewhat delicately to handle a three-state setup: +// +// State 1: No -fbounds-safety enabled anywhere, all macros below should act +// as-if -fbounds-safety doesn't exist. +// State 2: A file with -fbounds-safety enabled calling into files with or +// without -fbounds-safety. +// State 3: A file without -fbounds-safety enabled calling into files with +// -fbounds-safety. ABI breaking annotations must stay to force a +// build failure and force us to use non-ABI breaking annotations. +// +// Currently, we only allow non-ABI changing annotations in this file to ensure +// we don't accidentally change the ABI for public functions. + +#include + +#define WEBP_ASSUME_UNSAFE_INDEXABLE_ABI \ + __ptrcheck_abi_assume_unsafe_indexable() + +#define WEBP_COUNTED_BY(x) __counted_by(x) +#define WEBP_COUNTED_BY_OR_NULL(x) __counted_by_or_null(x) +#define WEBP_SIZED_BY(x) __sized_by(x) +#define WEBP_SIZED_BY_OR_NULL(x) __sized_by_or_null(x) +#define WEBP_ENDED_BY(x) __ended_by(x) + +#define WEBP_UNSAFE_INDEXABLE __unsafe_indexable +#define WEBP_SINGLE __single + +#define WEBP_UNSAFE_FORGE_SINGLE(typ, ptr) __unsafe_forge_single(typ, ptr) + +#define WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(typ, ptr, size) \ + __unsafe_forge_bidi_indexable(typ, ptr, size) + +// Provide memcpy/memset/memmove wrappers to make migration easier. +#define WEBP_UNSAFE_MEMCPY(dst, src, size) \ + do { \ + memcpy(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), \ + WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, src, size), size); \ + } while (0) + +#define WEBP_UNSAFE_MEMSET(dst, c, size) \ + do { \ + memset(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), c, size); \ + } while (0) + +#define WEBP_UNSAFE_MEMMOVE(dst, src, size) \ + do { \ + memmove(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, dst, size), \ + WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, src, size), size); \ + } while (0) + +#define WEBP_UNSAFE_MEMCMP(s1, s2, size) \ + memcmp(WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, s1, size), \ + WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, s2, size), size) + +#else // WEBP_SUPPORT_FBOUNDS_SAFETY + +#define WEBP_ASSUME_UNSAFE_INDEXABLE_ABI + +#define WEBP_COUNTED_BY(x) +#define WEBP_COUNTED_BY_OR_NULL(x) +#define WEBP_SIZED_BY(x) +#define WEBP_SIZED_BY_OR_NULL(x) +#define WEBP_ENDED_BY(x) + +#define WEBP_UNSAFE_INDEXABLE +#define WEBP_SINGLE + +#define WEBP_UNSAFE_MEMCPY(dst, src, size) memcpy(dst, src, size) +#define WEBP_UNSAFE_MEMSET(dst, c, size) memset(dst, c, size) +#define WEBP_UNSAFE_MEMMOVE(dst, src, size) memmove(dst, src, size) +#define WEBP_UNSAFE_MEMCMP(s1, s2, size) memcmp(s1, s2, size) + +#define WEBP_UNSAFE_FORGE_SINGLE(typ, ptr) ((typ)(ptr)) +#define WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(typ, ptr, size) ((typ)(ptr)) + +#endif // WEBP_SUPPORT_FBOUNDS_SAFETY + +// This macro exists to indicate intentionality with self-assignments and +// silence -Wself-assign compiler warnings. +#define WEBP_SELF_ASSIGN(x) x = x + #endif // WEBP_WEBP_TYPES_H_