1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
6*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
7*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
9*6777b538SAndroid Build Coastguard Worker #include <string.h>
10*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
11*6777b538SAndroid Build Coastguard Worker #include <sys/types.h>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include <algorithm>
14*6777b538SAndroid Build Coastguard Worker #include <limits>
15*6777b538SAndroid Build Coastguard Worker #include <memory>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/free_deleter.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/sanitizer_buildflags.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/partition_alloc_buildflags.h"
22*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX)
25*6777b538SAndroid Build Coastguard Worker #include <sys/mman.h>
26*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
27*6777b538SAndroid Build Coastguard Worker #endif
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker using std::nothrow;
30*6777b538SAndroid Build Coastguard Worker using std::numeric_limits;
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker namespace {
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker // This function acts as a compiler optimization barrier. We use it to
35*6777b538SAndroid Build Coastguard Worker // prevent the compiler from making an expression a compile-time constant.
36*6777b538SAndroid Build Coastguard Worker // We also use it so that the compiler doesn't discard certain return values
37*6777b538SAndroid Build Coastguard Worker // as something we don't need (see the comment with calloc below).
38*6777b538SAndroid Build Coastguard Worker template <typename Type>
HideValueFromCompiler(Type value)39*6777b538SAndroid Build Coastguard Worker NOINLINE Type HideValueFromCompiler(Type value) {
40*6777b538SAndroid Build Coastguard Worker #if defined(__GNUC__)
41*6777b538SAndroid Build Coastguard Worker // In a GCC compatible compiler (GCC or Clang), make this compiler barrier
42*6777b538SAndroid Build Coastguard Worker // more robust.
43*6777b538SAndroid Build Coastguard Worker __asm__ volatile ("" : "+r" (value));
44*6777b538SAndroid Build Coastguard Worker #endif // __GNUC__
45*6777b538SAndroid Build Coastguard Worker return value;
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker // There are platforms where these tests are known to fail. We would like to
49*6777b538SAndroid Build Coastguard Worker // be able to easily check the status on the bots, but marking tests as
50*6777b538SAndroid Build Coastguard Worker // FAILS_ is too clunky.
OverflowTestsSoftExpectTrue(bool overflow_detected)51*6777b538SAndroid Build Coastguard Worker void OverflowTestsSoftExpectTrue(bool overflow_detected) {
52*6777b538SAndroid Build Coastguard Worker if (!overflow_detected) {
53*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
54*6777b538SAndroid Build Coastguard Worker BUILDFLAG(IS_APPLE)
55*6777b538SAndroid Build Coastguard Worker // Sadly, on Linux, Android, and OSX we don't have a good story yet. Don't
56*6777b538SAndroid Build Coastguard Worker // fail the test, but report.
57*6777b538SAndroid Build Coastguard Worker printf("Platform has overflow: %s\n",
58*6777b538SAndroid Build Coastguard Worker !overflow_detected ? "yes." : "no.");
59*6777b538SAndroid Build Coastguard Worker #else
60*6777b538SAndroid Build Coastguard Worker // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT
61*6777b538SAndroid Build Coastguard Worker // aren't).
62*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(overflow_detected);
63*6777b538SAndroid Build Coastguard Worker #endif
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE) || defined(ADDRESS_SANITIZER) || \
68*6777b538SAndroid Build Coastguard Worker defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \
69*6777b538SAndroid Build Coastguard Worker BUILDFLAG(IS_HWASAN) || BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
70*6777b538SAndroid Build Coastguard Worker #define MAYBE_NewOverflow DISABLED_NewOverflow
71*6777b538SAndroid Build Coastguard Worker #else
72*6777b538SAndroid Build Coastguard Worker #define MAYBE_NewOverflow NewOverflow
73*6777b538SAndroid Build Coastguard Worker #endif
74*6777b538SAndroid Build Coastguard Worker // Test that array[TooBig][X] and array[X][TooBig] allocations fail and not
75*6777b538SAndroid Build Coastguard Worker // succeed with the wrong size allocation in case of size_t overflow. This
76*6777b538SAndroid Build Coastguard Worker // test is disabled on environments that operator new (nothrow) crashes in
77*6777b538SAndroid Build Coastguard Worker // case of size_t overflow.
78*6777b538SAndroid Build Coastguard Worker //
79*6777b538SAndroid Build Coastguard Worker // - iOS doesn't honor nothrow.
80*6777b538SAndroid Build Coastguard Worker // - XSan aborts when operator new returns nullptr.
81*6777b538SAndroid Build Coastguard Worker // - PartitionAlloc crashes by design when size_t overflows.
82*6777b538SAndroid Build Coastguard Worker //
83*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/927179): Fix the test on Mac.
TEST(SecurityTest,MAYBE_NewOverflow)84*6777b538SAndroid Build Coastguard Worker TEST(SecurityTest, MAYBE_NewOverflow) {
85*6777b538SAndroid Build Coastguard Worker const size_t kArraySize = 4096;
86*6777b538SAndroid Build Coastguard Worker // We want something "dynamic" here, so that the compiler doesn't
87*6777b538SAndroid Build Coastguard Worker // immediately reject crazy arrays.
88*6777b538SAndroid Build Coastguard Worker [[maybe_unused]] const size_t kDynamicArraySize =
89*6777b538SAndroid Build Coastguard Worker HideValueFromCompiler(kArraySize);
90*6777b538SAndroid Build Coastguard Worker const size_t kMaxSizeT = std::numeric_limits<size_t>::max();
91*6777b538SAndroid Build Coastguard Worker const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
92*6777b538SAndroid Build Coastguard Worker const size_t kDynamicArraySize2 = HideValueFromCompiler(kArraySize2);
93*6777b538SAndroid Build Coastguard Worker {
94*6777b538SAndroid Build Coastguard Worker std::unique_ptr<char[][kArraySize]> array_pointer(
95*6777b538SAndroid Build Coastguard Worker new (nothrow) char[kDynamicArraySize2][kArraySize]);
96*6777b538SAndroid Build Coastguard Worker // Prevent clang from optimizing away the whole test.
97*6777b538SAndroid Build Coastguard Worker char* volatile p = reinterpret_cast<char*>(array_pointer.get());
98*6777b538SAndroid Build Coastguard Worker OverflowTestsSoftExpectTrue(!p);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_64_BITS)
101*6777b538SAndroid Build Coastguard Worker // On Windows, the compiler prevents static array sizes of more than
102*6777b538SAndroid Build Coastguard Worker // 0x7fffffff (error C2148).
103*6777b538SAndroid Build Coastguard Worker #else
104*6777b538SAndroid Build Coastguard Worker {
105*6777b538SAndroid Build Coastguard Worker std::unique_ptr<char[][kArraySize2]> array_pointer(
106*6777b538SAndroid Build Coastguard Worker new (nothrow) char[kDynamicArraySize][kArraySize2]);
107*6777b538SAndroid Build Coastguard Worker // Prevent clang from optimizing away the whole test.
108*6777b538SAndroid Build Coastguard Worker char* volatile p = reinterpret_cast<char*>(array_pointer.get());
109*6777b538SAndroid Build Coastguard Worker OverflowTestsSoftExpectTrue(!p);
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN) && defined(ARCH_CPU_64_BITS)
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker } // namespace
115