wrappers_c_checks.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. #ifndef SCUDO_CHECKS_H_
  9. #define SCUDO_CHECKS_H_
  10. #include "common.h"
  11. #include <errno.h>
  12. #ifndef __has_builtin
  13. #define __has_builtin(X) 0
  14. #endif
  15. namespace scudo {
  16. // A common errno setting logic shared by almost all Scudo C wrappers.
  17. inline void *setErrnoOnNull(void *Ptr) {
  18. if (UNLIKELY(!Ptr))
  19. errno = ENOMEM;
  20. return Ptr;
  21. }
  22. // Checks return true on failure.
  23. // Checks aligned_alloc() parameters, verifies that the alignment is a power of
  24. // two and that the size is a multiple of alignment.
  25. inline bool checkAlignedAllocAlignmentAndSize(uptr Alignment, uptr Size) {
  26. return Alignment == 0 || !isPowerOfTwo(Alignment) ||
  27. !isAligned(Size, Alignment);
  28. }
  29. // Checks posix_memalign() parameters, verifies that alignment is a power of two
  30. // and a multiple of sizeof(void *).
  31. inline bool checkPosixMemalignAlignment(uptr Alignment) {
  32. return Alignment == 0 || !isPowerOfTwo(Alignment) ||
  33. !isAligned(Alignment, sizeof(void *));
  34. }
  35. // Returns true if calloc(Size, N) overflows on Size*N calculation. Use a
  36. // builtin supported by recent clang & GCC if it exists, otherwise fallback to a
  37. // costly division.
  38. inline bool checkForCallocOverflow(uptr Size, uptr N, uptr *Product) {
  39. #if __has_builtin(__builtin_umull_overflow) && (SCUDO_WORDSIZE == 64U)
  40. return __builtin_umull_overflow(Size, N,
  41. reinterpret_cast<unsigned long *>(Product));
  42. #elif __has_builtin(__builtin_umul_overflow) && (SCUDO_WORDSIZE == 32U)
  43. // On, e.g. armv7, uptr/uintptr_t may be defined as unsigned long
  44. return __builtin_umul_overflow(Size, N,
  45. reinterpret_cast<unsigned int *>(Product));
  46. #else
  47. *Product = Size * N;
  48. if (!Size)
  49. return false;
  50. return (*Product / Size) != N;
  51. #endif
  52. }
  53. // Returns true if the size passed to pvalloc overflows when rounded to the next
  54. // multiple of PageSize.
  55. inline bool checkForPvallocOverflow(uptr Size, uptr PageSize) {
  56. return roundUpTo(Size, PageSize) < Size;
  57. }
  58. } // namespace scudo
  59. #endif // SCUDO_CHECKS_H_