mirror of
https://github.com/webmproject/libwebp.git
synced 2025-08-28 14:52:28 +02:00
Create src/utils/bounds_safety.h
The macros in src/utils/bounds_safety.h exist to ensure libwebp stays portable. This also provides wrappers around common functions like memcpy/memset/memmove, which are useful as part of the migration. Memcpy (et al.) wrappers aren't expected to exist forever, and can be removed after the codebase is fully annotated. There's some complexity here due to the number of states we need to support: 1) Off everywhere 2) Building libwebp (some or all) with -fbounds-safety 3) Linking against libwebp that was built with -fbounds-safety 4) Inter-operation with C++ Change-Id: I789f0a94f25b70cab172d5b3f5e6b12de3a34bb4
This commit is contained in:
@@ -414,6 +414,7 @@ add_library(webp $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdsp>
|
||||
$<TARGET_OBJECTS:webpencode> $<TARGET_OBJECTS:webputils>)
|
||||
if(WEBP_ENABLE_FBOUNDS_SAFETY)
|
||||
# Enable -fbounds-safety only for webputils for now.
|
||||
add_definitions(-DWEBP_SUPPORT_FBOUNDS_SAFETY=1)
|
||||
target_compile_options(webputils PRIVATE -fbounds-safety)
|
||||
endif()
|
||||
|
||||
|
113
src/utils/bounds_safety.h
Normal file
113
src/utils/bounds_safety.h
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Adds compatibility / portability macros to support usage of -fbounds-safety
|
||||
|
||||
#ifndef WEBP_UTILS_BOUNDS_SAFETY_H_
|
||||
#define WEBP_UTILS_BOUNDS_SAFETY_H_
|
||||
|
||||
#include <string.h> // For memcpy and friends
|
||||
|
||||
// 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
|
||||
// disappear if they're expected.
|
||||
//
|
||||
// In ptrcheck.h provided by the compiler, ABI changing annotations do not
|
||||
// "vanish" under any build configuration. This is intentional. Consider the
|
||||
// following example:
|
||||
//
|
||||
// == Safe.h, where Safe.c is always compiled with -fbounds-safety ==
|
||||
// Forward declare my_function, implemented in Safe.c
|
||||
// void my_function(char *__bidi_indexable ptr);
|
||||
//
|
||||
// If we have a project that does not use -fbounds-safety, and we want to call
|
||||
// my_function that was pre-built with -fbounds-safety, this annotation cannot
|
||||
// vanish or there'll be an ABI mismatch, which may fail to compile or have
|
||||
// worse behaviors at runtime.
|
||||
//
|
||||
// TODO: https://issues.webmproject.org/432511225 - In the future, we should
|
||||
// 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 <ptrcheck.h>
|
||||
|
||||
#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
|
||||
// forward-indexed.
|
||||
// * __bidi_indexable (bidirectional indexable) is
|
||||
// { ptr_begin, ptr_curr, ptr_end }
|
||||
// and can be both forward and backward indexed.
|
||||
// See https://clang.llvm.org/docs/BoundsSafety.html for more comprehensive
|
||||
// documentation
|
||||
#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)
|
||||
|
||||
#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_FORGE_SINGLE(typ, ptr) ((typ)(ptr))
|
||||
#define WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(typ, ptr, size) ((typ)(ptr))
|
||||
|
||||
#endif // WEBP_SUPPORT_FBOUNDS_SAFETY
|
||||
#endif // WEBP_UTILS_BOUNDS_SAFETY_H_
|
Reference in New Issue
Block a user