1 //===-- wrappers_c_checks.h -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef SCUDO_CHECKS_H_ 10 #define SCUDO_CHECKS_H_ 11 12 #include "common.h" 13 14 #include <errno.h> 15 16 #ifndef __has_builtin 17 #define __has_builtin(X) 0 18 #endif 19 20 namespace scudo { 21 22 // A common errno setting logic shared by almost all Scudo C wrappers. 23 inline void *setErrnoOnNull(void *Ptr) { 24 if (UNLIKELY(!Ptr)) 25 errno = ENOMEM; 26 return Ptr; 27 } 28 29 // Checks return true on failure. 30 31 // Checks aligned_alloc() parameters, verifies that the alignment is a power of 32 // two and that the size is a multiple of alignment. 33 inline bool checkAlignedAllocAlignmentAndSize(uptr Alignment, uptr Size) { 34 return !isPowerOfTwo(Alignment) || !isAligned(Size, Alignment); 35 } 36 37 // Checks posix_memalign() parameters, verifies that alignment is a power of two 38 // and a multiple of sizeof(void *). 39 inline bool checkPosixMemalignAlignment(uptr Alignment) { 40 return !isPowerOfTwo(Alignment) || !isAligned(Alignment, sizeof(void *)); 41 } 42 43 // Returns true if calloc(Size, N) overflows on Size*N calculation. Use a 44 // builtin supported by recent clang & GCC if it exists, otherwise fallback to a 45 // costly division. 46 inline bool checkForCallocOverflow(uptr Size, uptr N, uptr *Product) { 47 #if __has_builtin(__builtin_umull_overflow) && (SCUDO_WORDSIZE == 64U) 48 return __builtin_umull_overflow(Size, N, 49 reinterpret_cast<unsigned long *>(Product)); 50 #elif __has_builtin(__builtin_umul_overflow) && (SCUDO_WORDSIZE == 32U) 51 // On, e.g. armv7, uptr/uintptr_t may be defined as unsigned long 52 return __builtin_umul_overflow(Size, N, 53 reinterpret_cast<unsigned int *>(Product)); 54 #else 55 *Product = Size * N; 56 if (!Size) 57 return false; 58 return (*Product / Size) != N; 59 #endif 60 } 61 62 // Returns true if the size passed to pvalloc overflows when rounded to the next 63 // multiple of PageSize. 64 inline bool checkForPvallocOverflow(uptr Size, uptr PageSize) { 65 return roundUp(Size, PageSize) < Size; 66 } 67 68 } // namespace scudo 69 70 #endif // SCUDO_CHECKS_H_ 71