| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/compiler_specific.h" |
| #include "base/debug/alias.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| // TODO(crbug.com/386992829): differentiate `-fsanitize=array-bounds` |
| // from a full-on UBSan build, and remove this particular gating |
| // pattern. |
| #if __has_feature(undefined_behavior_sanitizer) |
| |
| template <typename T> |
| void DoNotOptimize(T t) { |
| // Ensure the compiler does not optimize the access out before the hardening |
| // check. See https://github.com/llvm/llvm-project/issues/89432 |
| base::debug::Alias(&t); |
| } |
| |
| TEST(CompilerHardeningDeathTest, ArrayOutOfBounds) { |
| // Set up two arrays, and force them on the stack. This means one will be |
| // placed after the other and provide some buffer for the out-of-bounds |
| // access. (We wish to distinguish an crash from the memory error from a clean |
| // crash from the compiler hardening.) |
| char a[10] = {0}; |
| char b[10] = {0}; |
| base::debug::Alias(a); |
| base::debug::Alias(a); |
| |
| int idx = 10; |
| // Prevent the compiler from reasoning about the value of `idx` and rejecting |
| // the array access at compile time. |
| base::debug::Alias(&idx); |
| |
| // SAFETY: Although out of bounds, this is actually safe when built with |
| // -fsanitize=array-bounds. The warning is a false positive. See |
| // https://github.com/llvm/llvm-project/issues/87284 |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(DoNotOptimize(a[idx])), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(DoNotOptimize(b[idx])), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(a[idx] = 0), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(b[idx] = 0), ""); |
| |
| idx = -1; |
| // SAFETY: Although out of bounds, this is actually safe when built with |
| // -fsanitize=array-bounds. The warning is a false positive. See |
| // https://github.com/llvm/llvm-project/issues/87284 |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(DoNotOptimize(a[idx])), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(DoNotOptimize(b[idx])), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(a[idx] = 0), ""); |
| EXPECT_DEATH_IF_SUPPORTED(UNSAFE_BUFFERS(b[idx] = 0), ""); |
| } |
| |
| #endif // !__has_feature(undefined_behavior_sanitizer) |
| |
| } // namespace |