1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/asan_runtime.h"
16 :
17 : #include "base/command_line.h"
18 : #include "base/environment.h"
19 : #include "base/string_number_conversions.h"
20 : #include "base/utf_string_conversions.h"
21 : #include "base/memory/scoped_ptr.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/agent/asan/asan_heap.h"
24 : #include "syzygy/agent/asan/unittest_util.h"
25 :
26 : namespace agent {
27 : namespace asan {
28 :
29 : namespace {
30 :
31 : using agent::asan::HeapProxy;
32 :
33 : // A derived class to expose protected members for unit-testing.
34 : class TestAsanRuntime : public AsanRuntime {
35 : public:
36 : using AsanRuntime::AsanFlags;
37 : using AsanRuntime::kBottomFramesToSkip;
38 : using AsanRuntime::kCompressionReportingPeriod;
39 : using AsanRuntime::kIgnoredStackIds;
40 : using AsanRuntime::kQuarantineSize;
41 : using AsanRuntime::kSyzyAsanEnvVar;
42 : using AsanRuntime::PropagateFlagsValues;
43 : using AsanRuntime::flags;
44 : using AsanRuntime::set_flags;
45 : };
46 :
47 : class AsanRuntimeTest : public testing::TestWithAsanLogger {
48 : public:
49 E : AsanRuntimeTest() : current_command_line_(CommandLine::NO_PROGRAM) {
50 E : }
51 :
52 E : void SetUp() OVERRIDE {
53 E : testing::TestWithAsanLogger::SetUp();
54 E : scoped_ptr<base::Environment> env(base::Environment::Create());
55 E : ASSERT_TRUE(env.get() != NULL);
56 E : env->UnSetVar(TestAsanRuntime::kSyzyAsanEnvVar);
57 E : }
58 :
59 : // The test runtime instance.
60 : TestAsanRuntime asan_runtime_;
61 :
62 : // The value of the command-line that we want to test.
63 : CommandLine current_command_line_;
64 : };
65 :
66 : bool callback_called = false;
67 :
68 : // A simple callback that change the value of a boolean to indicate that it has
69 : // been called.
70 E : void TestCallback(CONTEXT* context) {
71 E : callback_called = true;
72 E : }
73 :
74 : } // namespace
75 :
76 E : TEST_F(AsanRuntimeTest, SetUpAndTearDown) {
77 : ASSERT_NO_FATAL_FAILURE(
78 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
79 E : ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
80 E : }
81 :
82 E : TEST_F(AsanRuntimeTest, OnError) {
83 : ASSERT_NO_FATAL_FAILURE(
84 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
85 E : asan_runtime_.SetErrorCallBack(&TestCallback);
86 E : callback_called = false;
87 : CONTEXT context;
88 E : RtlCaptureContext(&context);
89 E : StackCapture stack;
90 E : stack.InitFromStack();
91 E : asan_runtime_.OnError(&context);
92 E : ASSERT_EQ(true, callback_called);
93 E : ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
94 E : }
95 :
96 E : TEST_F(AsanRuntimeTest, SetDefaultQuarantineMaxSize) {
97 : // Initialize the flags with the original command line.
98 : ASSERT_NO_FATAL_FAILURE(
99 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
100 :
101 : // Double the max size of the quarantine.
102 : unsigned int quarantine_max_size =
103 E : HeapProxy::default_quarantine_max_size() * 2;
104 : // Increments the quarantine max size if it was set to 0.
105 E : if (quarantine_max_size == 0)
106 i : quarantine_max_size++;
107 E : DCHECK_GT(quarantine_max_size, 0U);
108 E : std::string quarantine_max_size_str = base::UintToString(quarantine_max_size);
109 : current_command_line_.AppendSwitchASCII(TestAsanRuntime::kQuarantineSize,
110 E : quarantine_max_size_str);
111 :
112 : // Tear down the runtime and restart it with a different command line.
113 E : ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
114 : ASSERT_NO_FATAL_FAILURE(
115 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
116 :
117 : // Ensure that the quarantine max size has been modified.
118 E : EXPECT_EQ(quarantine_max_size, HeapProxy::default_quarantine_max_size());
119 :
120 : // Ensure that the heap proxies use the new quarantine max size.
121 E : HeapProxy heap_proxy(asan_runtime_.stack_cache(), asan_runtime_.logger());
122 E : ASSERT_TRUE(heap_proxy.Create(0, 0, 0));
123 E : EXPECT_EQ(quarantine_max_size, heap_proxy.quarantine_max_size());
124 E : ASSERT_TRUE(heap_proxy.Destroy());
125 E : }
126 :
127 E : TEST_F(AsanRuntimeTest, SetCompressionReportingPeriod) {
128 : ASSERT_EQ(StackCaptureCache::GetDefaultCompressionReportingPeriod(),
129 E : StackCaptureCache::compression_reporting_period());
130 :
131 : size_t new_period =
132 E : StackCaptureCache::GetDefaultCompressionReportingPeriod() + 1024;
133 E : std::string new_period_str = base::UintToString(new_period);
134 : current_command_line_.AppendSwitchASCII(
135 E : TestAsanRuntime::kCompressionReportingPeriod, new_period_str);
136 :
137 : ASSERT_NO_FATAL_FAILURE(
138 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
139 :
140 : // Ensure that the compression reporting period has been modified.
141 E : EXPECT_EQ(new_period, StackCaptureCache::compression_reporting_period());
142 E : }
143 :
144 E : TEST_F(AsanRuntimeTest, SetBottomFramesToSkip) {
145 E : size_t frames_to_skip = StackCapture::bottom_frames_to_skip() + 1;
146 E : std::string new_frames_to_skip_str = base::UintToString(frames_to_skip);
147 : current_command_line_.AppendSwitchASCII(
148 E : TestAsanRuntime::kBottomFramesToSkip, new_frames_to_skip_str);
149 :
150 : ASSERT_NO_FATAL_FAILURE(
151 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
152 :
153 E : EXPECT_EQ(frames_to_skip, StackCapture::bottom_frames_to_skip());
154 E : }
155 :
156 E : TEST_F(AsanRuntimeTest, IgnoredStackIds) {
157 E : std::string ignored_stack_ids = "0x1;0X7E577E57;0xCAFEBABE;0xffffffff";
158 : current_command_line_.AppendSwitchASCII(
159 E : TestAsanRuntime::kIgnoredStackIds, ignored_stack_ids);
160 :
161 : ASSERT_NO_FATAL_FAILURE(
162 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
163 :
164 : EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0x1) !=
165 E : asan_runtime_.flags()->ignored_stack_ids.end());
166 : EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0x7E577E57) !=
167 E : asan_runtime_.flags()->ignored_stack_ids.end());
168 : EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0xCAFEBABE) !=
169 E : asan_runtime_.flags()->ignored_stack_ids.end());
170 : EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0xFFFFFFFF) !=
171 E : asan_runtime_.flags()->ignored_stack_ids.end());
172 E : }
173 :
174 E : TEST_F(AsanRuntimeTest, SetFlags) {
175 : ASSERT_NO_FATAL_FAILURE(
176 E : asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
177 :
178 E : TestAsanRuntime::AsanFlags flags;
179 E : flags.quarantine_size = HeapProxy::default_quarantine_max_size() - 1;
180 E : ASSERT_LT(0U, flags.quarantine_size);
181 : flags.reporting_period =
182 E : StackCaptureCache::GetDefaultCompressionReportingPeriod() - 1;
183 E : ASSERT_LT(0U, flags.reporting_period);
184 : flags.bottom_frames_to_skip =
185 E : StackCapture::bottom_frames_to_skip() - 1;
186 E : ASSERT_LT(0U, flags.bottom_frames_to_skip);
187 : flags.max_num_frames =
188 E : asan_runtime_.stack_cache()->max_num_frames() - 1;
189 E : ASSERT_LT(0U, flags.max_num_frames);
190 E : asan_runtime_.set_flags(&flags);
191 E : asan_runtime_.PropagateFlagsValues();
192 :
193 E : ASSERT_EQ(flags.quarantine_size, HeapProxy::default_quarantine_max_size());
194 : ASSERT_EQ(flags.reporting_period,
195 E : StackCaptureCache::compression_reporting_period());
196 E : ASSERT_EQ(flags.bottom_frames_to_skip, StackCapture::bottom_frames_to_skip());
197 : ASSERT_EQ(flags.max_num_frames,
198 E : asan_runtime_.stack_cache()->max_num_frames());
199 E : }
200 :
201 : } // namespace asan
202 : } // namespace agent
|