1321188Sdim//===-- sanitizer_allocator_checks.h ----------------------------*- C++ -*-===//
2321188Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6321188Sdim//
7321188Sdim//===----------------------------------------------------------------------===//
8321188Sdim//
9321188Sdim// Various checks shared between ThreadSanitizer, MemorySanitizer, etc. memory
10321188Sdim// allocators.
11321188Sdim//
12321188Sdim//===----------------------------------------------------------------------===//
13321188Sdim
14321188Sdim#ifndef SANITIZER_ALLOCATOR_CHECKS_H
15321188Sdim#define SANITIZER_ALLOCATOR_CHECKS_H
16321188Sdim
17321188Sdim#include "sanitizer_internal_defs.h"
18321188Sdim#include "sanitizer_common.h"
19321188Sdim#include "sanitizer_platform.h"
20321188Sdim
21321188Sdimnamespace __sanitizer {
22321188Sdim
23327952Sdim// The following is defined in a separate compilation unit to avoid pulling in
24327952Sdim// sanitizer_errno.h in this header, which leads to conflicts when other system
25327952Sdim// headers include errno.h. This is usually the result of an unlikely event,
26327952Sdim// and as such we do not care as much about having it inlined.
27327952Sdimvoid SetErrnoToENOMEM();
28327952Sdim
29321188Sdim// A common errno setting logic shared by almost all sanitizer allocator APIs.
30321188SdimINLINE void *SetErrnoOnNull(void *ptr) {
31321188Sdim  if (UNLIKELY(!ptr))
32327952Sdim    SetErrnoToENOMEM();
33321188Sdim  return ptr;
34321188Sdim}
35321188Sdim
36321188Sdim// In case of the check failure, the caller of the following Check... functions
37321188Sdim// should "return POLICY::OnBadRequest();" where POLICY is the current allocator
38321188Sdim// failure handling policy.
39321188Sdim
40321188Sdim// Checks aligned_alloc() parameters, verifies that the alignment is a power of
41321188Sdim// two and that the size is a multiple of alignment for POSIX implementation,
42321188Sdim// and a bit relaxed requirement for non-POSIX ones, that the size is a multiple
43321188Sdim// of alignment.
44321188SdimINLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
45321188Sdim#if SANITIZER_POSIX
46341825Sdim  return alignment != 0 && IsPowerOfTwo(alignment) &&
47341825Sdim         (size & (alignment - 1)) == 0;
48321188Sdim#else
49341825Sdim  return alignment != 0 && size % alignment == 0;
50321188Sdim#endif
51321188Sdim}
52321188Sdim
53321188Sdim// Checks posix_memalign() parameters, verifies that alignment is a power of two
54321188Sdim// and a multiple of sizeof(void *).
55321188SdimINLINE bool CheckPosixMemalignAlignment(uptr alignment) {
56341825Sdim  return alignment != 0 && IsPowerOfTwo(alignment) &&
57360784Sdim         (alignment % sizeof(void *)) == 0;
58321188Sdim}
59321188Sdim
60321188Sdim// Returns true if calloc(size, n) call overflows on size*n calculation.
61321188SdimINLINE bool CheckForCallocOverflow(uptr size, uptr n) {
62321188Sdim  if (!size)
63321188Sdim    return false;
64321188Sdim  uptr max = (uptr)-1L;
65321188Sdim  return (max / size) < n;
66321188Sdim}
67321188Sdim
68327952Sdim// Returns true if the size passed to pvalloc overflows when rounded to the next
69327952Sdim// multiple of page_size.
70327952SdimINLINE bool CheckForPvallocOverflow(uptr size, uptr page_size) {
71327952Sdim  return RoundUpTo(size, page_size) < size;
72327952Sdim}
73327952Sdim
74321188Sdim} // namespace __sanitizer
75321188Sdim
76321188Sdim#endif  // SANITIZER_ALLOCATOR_CHECKS_H
77