1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/environment.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/path_service.h"
12 #include "base/win/scoped_handle.h"
13 #include "base/win/windows_version.h"
14 #include "sandbox/win/tests/common/controller.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 class AddressSanitizerTests
: public ::testing::Test
{
22 env_
.reset(base::Environment::Create());
23 had_asan_options_
= env_
->GetVar("ASAN_OPTIONS", &old_asan_options_
);
27 if (had_asan_options_
)
28 ASSERT_TRUE(env_
->SetVar("ASAN_OPTIONS", old_asan_options_
));
30 env_
->UnSetVar("ASAN_OPTIONS");
34 scoped_ptr
<base::Environment
> env_
;
35 bool had_asan_options_
;
36 std::string old_asan_options_
;
39 SBOX_TESTS_COMMAND
int AddressSanitizerTests_Report(int argc
, wchar_t** argv
) {
40 // AddressSanitizer should detect an out of bounds write (heap buffer
41 // overflow) in this code.
42 volatile int idx
= 42;
43 int *blah
= new int[42];
46 return SBOX_TEST_FAILED
;
49 TEST_F(AddressSanitizerTests
, TestAddressSanitizer
) {
50 // This test is only supposed to work when using AddressSanitizer.
51 // However, ASan/Win is not on the CQ yet, so compiler breakages may get into
52 // the code unnoticed. To avoid that, we compile this test in all Windows
53 // builds, but only run the AddressSanitizer-specific part of the test when
54 // compiled with AddressSanitizer.
55 #if defined(ADDRESS_SANITIZER)
56 bool asan_build
= true;
58 bool asan_build
= false;
60 base::ScopedTempDir temp_directory
;
61 base::FilePath temp_file_name
;
62 ASSERT_TRUE(temp_directory
.CreateUniqueTempDir());
63 ASSERT_TRUE(CreateTemporaryFileInDir(temp_directory
.path(), &temp_file_name
));
65 SECURITY_ATTRIBUTES attrs
= {};
66 attrs
.nLength
= sizeof(attrs
);
67 attrs
.bInheritHandle
= TRUE
;
68 base::win::ScopedHandle
tmp_handle(
69 CreateFile(temp_file_name
.value().c_str(), GENERIC_WRITE
,
70 FILE_SHARE_WRITE
| FILE_SHARE_READ
| FILE_SHARE_DELETE
,
71 &attrs
, OPEN_EXISTING
, 0, NULL
));
72 EXPECT_TRUE(tmp_handle
.IsValid());
75 ASSERT_EQ(SBOX_ALL_OK
, runner
.GetPolicy()->SetStderrHandle(tmp_handle
.Get()));
78 ASSERT_TRUE(PathService::Get(base::FILE_EXE
, &exe
));
79 base::FilePath pdb_path
= exe
.DirName().Append(L
"*.pdb");
80 ASSERT_TRUE(runner
.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY
,
81 pdb_path
.value().c_str()));
83 env_
->SetVar("ASAN_OPTIONS", "exitcode=123");
85 int result
= runner
.RunTest(L
"AddressSanitizerTests_Report");
86 EXPECT_EQ(123, result
);
89 ASSERT_TRUE(base::ReadFileToString(base::FilePath(temp_file_name
), &data
));
90 // Redirection uses a feature that was added in Windows Vista.
91 if (base::win::GetVersion() >= base::win::VERSION_VISTA
) {
93 strstr(data
.c_str(), "ERROR: AddressSanitizer: heap-buffer-overflow"))
94 << "There doesn't seem to be an ASan report:\n" << data
;
95 ASSERT_TRUE(strstr(data
.c_str(), "AddressSanitizerTests_Report"))
96 << "The ASan report doesn't appear to be symbolized:\n" << data
;
97 ASSERT_TRUE(strstr(data
.c_str(), strrchr(__FILE__
, '\\')))
98 << "The stack trace doesn't have a correct filename:\n" << data
;
100 LOG(WARNING
) << "Pre-Vista versions are not supported.";
103 LOG(WARNING
) << "Not an AddressSanitizer build, skipping the run.";