Don't preload rarely seen large images
[chromium-blink-merge.git] / sandbox / win / src / policy_opcodes_unittest.cc
blobc999348fa8a7a89c524d5341ecb069ba279168e9
1 // Copyright (c) 2006-2008 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.
5 #include "sandbox/win/src/sandbox_types.h"
6 #include "sandbox/win/src/sandbox_nt_types.h"
7 #include "sandbox/win/src/policy_engine_params.h"
8 #include "sandbox/win/src/policy_engine_opcodes.h"
9 #include "testing/gtest/include/gtest/gtest.h"
12 #define INIT_GLOBAL_RTL(member) \
13 g_nt.member = reinterpret_cast<member##Function>( \
14 ::GetProcAddress(ntdll, #member)); \
15 if (NULL == g_nt.member) \
16 return false
18 namespace sandbox {
20 const size_t kOpcodeMemory = 1024;
22 SANDBOX_INTERCEPT NtExports g_nt;
24 bool SetupNtdllImports() {
25 HMODULE ntdll = ::GetModuleHandle(kNtdllName);
27 INIT_GLOBAL_RTL(RtlAllocateHeap);
28 INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
29 INIT_GLOBAL_RTL(RtlCompareUnicodeString);
30 INIT_GLOBAL_RTL(RtlCreateHeap);
31 INIT_GLOBAL_RTL(RtlDestroyHeap);
32 INIT_GLOBAL_RTL(RtlFreeHeap);
33 INIT_GLOBAL_RTL(_strnicmp);
34 INIT_GLOBAL_RTL(strlen);
35 INIT_GLOBAL_RTL(wcslen);
37 return true;
40 TEST(PolicyEngineTest, ParameterSetTest) {
41 void* pv1 = reinterpret_cast<void*>(0x477EAA5);
42 const void* pv2 = reinterpret_cast<void*>(0x987654);
43 ParameterSet pset1 = ParamPickerMake(pv1);
44 ParameterSet pset2 = ParamPickerMake(pv2);
46 // Test that we can store and retrieve a void pointer:
47 const void* result1 =0;
48 uint32 result2 = 0;
49 EXPECT_TRUE(pset1.Get(&result1));
50 EXPECT_TRUE(pv1 == result1);
51 EXPECT_FALSE(pset1.Get(&result2));
52 EXPECT_TRUE(pset2.Get(&result1));
53 EXPECT_TRUE(pv2 == result1);
54 EXPECT_FALSE(pset2.Get(&result2));
56 // Test that we can store and retrieve a uint32:
57 uint32 number = 12747;
58 ParameterSet pset3 = ParamPickerMake(number);
59 EXPECT_FALSE(pset3.Get(&result1));
60 EXPECT_TRUE(pset3.Get(&result2));
61 EXPECT_EQ(number, result2);
63 // Test that we can store and retrieve a string:
64 const wchar_t* txt = L"S231L";
65 ParameterSet pset4 = ParamPickerMake(txt);
66 const wchar_t* result3 = NULL;
67 EXPECT_TRUE(pset4.Get(&result3));
68 EXPECT_EQ(0, wcscmp(txt, result3));
71 TEST(PolicyEngineTest, OpcodeConstraints) {
72 // Test that PolicyOpcode has no virtual functions
73 // because these objects are copied over to other processes
74 // so they cannot have vtables.
75 EXPECT_FALSE(__is_polymorphic(PolicyOpcode));
76 // Keep developers from adding smarts to the opcodes which should
77 // be pretty much a bag of bytes with a OO interface.
78 EXPECT_TRUE(__has_trivial_destructor(PolicyOpcode));
79 EXPECT_TRUE(__has_trivial_constructor(PolicyOpcode));
80 EXPECT_TRUE(__has_trivial_copy(PolicyOpcode));
83 TEST(PolicyEngineTest, TrueFalseOpcodes) {
84 void* dummy = NULL;
85 ParameterSet ppb1 = ParamPickerMake(dummy);
86 char memory[kOpcodeMemory];
87 OpcodeFactory opcode_maker(memory, sizeof(memory));
89 // This opcode always evaluates to true.
90 PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
91 ASSERT_NE(nullptr, op1);
92 EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&ppb1, 1, NULL));
93 EXPECT_FALSE(op1->IsAction());
95 // This opcode always evaluates to false.
96 PolicyOpcode* op2 = opcode_maker.MakeOpAlwaysTrue(kPolNone);
97 ASSERT_NE(nullptr, op2);
98 EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL));
100 // Nulls not allowed on the params.
101 EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 0, NULL));
102 EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 1, NULL));
104 // True and False opcodes do not 'require' a number of parameters
105 EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 0, NULL));
106 EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL));
108 // Test Inverting the logic. Note that inversion is done outside
109 // any particular opcode evaluation so no need to repeat for all
110 // opcodes.
111 PolicyOpcode* op3 = opcode_maker.MakeOpAlwaysFalse(kPolNegateEval);
112 ASSERT_NE(nullptr, op3);
113 EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&ppb1, 1, NULL));
114 PolicyOpcode* op4 = opcode_maker.MakeOpAlwaysTrue(kPolNegateEval);
115 ASSERT_NE(nullptr, op4);
116 EXPECT_EQ(EVAL_FALSE, op4->Evaluate(&ppb1, 1, NULL));
118 // Test that we clear the match context
119 PolicyOpcode* op5 = opcode_maker.MakeOpAlwaysTrue(kPolClearContext);
120 ASSERT_NE(nullptr, op5);
121 MatchContext context;
122 context.position = 1;
123 context.options = kPolUseOREval;
124 EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&ppb1, 1, &context));
125 EXPECT_EQ(0, context.position);
126 MatchContext context2;
127 EXPECT_EQ(context2.options, context.options);
130 TEST(PolicyEngineTest, OpcodeMakerCase1) {
131 // Testing that the opcode maker does not overrun the
132 // supplied buffer. It should only be able to make 'count' opcodes.
133 void* dummy = NULL;
134 ParameterSet ppb1 = ParamPickerMake(dummy);
136 char memory[kOpcodeMemory];
137 OpcodeFactory opcode_maker(memory, sizeof(memory));
138 size_t count = sizeof(memory) / sizeof(PolicyOpcode);
140 for (size_t ix =0; ix != count; ++ix) {
141 PolicyOpcode* op = opcode_maker.MakeOpAlwaysFalse(kPolNone);
142 ASSERT_NE(nullptr, op);
143 EXPECT_EQ(EVAL_FALSE, op->Evaluate(&ppb1, 1, NULL));
145 // There should be no room more another opcode:
146 PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
147 ASSERT_EQ(nullptr, op1);
150 TEST(PolicyEngineTest, OpcodeMakerCase2) {
151 SetupNtdllImports();
152 // Testing that the opcode maker does not overrun the
153 // supplied buffer. It should only be able to make 'count' opcodes.
154 // The difference with the previous test is that this opcodes allocate
155 // the string 'txt2' inside the same buffer.
156 const wchar_t* txt1 = L"1234";
157 const wchar_t txt2[] = L"123";
159 ParameterSet ppb1 = ParamPickerMake(txt1);
160 MatchContext mc1;
162 char memory[kOpcodeMemory];
163 OpcodeFactory opcode_maker(memory, sizeof(memory));
164 size_t count = sizeof(memory) / (sizeof(PolicyOpcode) + sizeof(txt2));
166 // Test that it does not overrun the buffer.
167 for (size_t ix =0; ix != count; ++ix) {
168 PolicyOpcode* op = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
169 CASE_SENSITIVE,
170 kPolClearContext);
171 ASSERT_NE(nullptr, op);
172 EXPECT_EQ(EVAL_TRUE, op->Evaluate(&ppb1, 1, &mc1));
175 // There should be no room more another opcode:
176 PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
177 CASE_SENSITIVE,
178 kPolNone);
179 ASSERT_EQ(nullptr, op1);
182 TEST(PolicyEngineTest, IntegerOpcodes) {
183 const wchar_t* txt = L"abcdef";
184 uint32 num1 = 42;
185 uint32 num2 = 113377;
187 ParameterSet pp_wrong1 = ParamPickerMake(txt);
188 ParameterSet pp_num1 = ParamPickerMake(num1);
189 ParameterSet pp_num2 = ParamPickerMake(num2);
191 char memory[kOpcodeMemory];
192 OpcodeFactory opcode_maker(memory, sizeof(memory));
194 // Test basic match for uint32s 42 == 42 and 42 != 113377.
195 PolicyOpcode* op_m42 = opcode_maker.MakeOpNumberMatch(0, 42UL, kPolNone);
196 ASSERT_NE(nullptr, op_m42);
197 EXPECT_EQ(EVAL_TRUE, op_m42->Evaluate(&pp_num1, 1, NULL));
198 EXPECT_EQ(EVAL_FALSE, op_m42->Evaluate(&pp_num2, 1, NULL));
199 EXPECT_EQ(EVAL_ERROR, op_m42->Evaluate(&pp_wrong1, 1, NULL));
201 // Test basic match for void pointers.
202 const void* vp = NULL;
203 ParameterSet pp_num3 = ParamPickerMake(vp);
204 PolicyOpcode* op_vp_null = opcode_maker.MakeOpVoidPtrMatch(0, NULL,
205 kPolNone);
206 ASSERT_NE(nullptr, op_vp_null);
207 EXPECT_EQ(EVAL_TRUE, op_vp_null->Evaluate(&pp_num3, 1, NULL));
208 EXPECT_EQ(EVAL_FALSE, op_vp_null->Evaluate(&pp_num1, 1, NULL));
209 EXPECT_EQ(EVAL_ERROR, op_vp_null->Evaluate(&pp_wrong1, 1, NULL));
211 // Basic range test [41 43] (inclusive).
212 PolicyOpcode* op_range1 =
213 opcode_maker.MakeOpNumberMatchRange(0, 41, 43, kPolNone);
214 ASSERT_NE(nullptr, op_range1);
215 EXPECT_EQ(EVAL_TRUE, op_range1->Evaluate(&pp_num1, 1, NULL));
216 EXPECT_EQ(EVAL_FALSE, op_range1->Evaluate(&pp_num2, 1, NULL));
217 EXPECT_EQ(EVAL_ERROR, op_range1->Evaluate(&pp_wrong1, 1, NULL));
220 TEST(PolicyEngineTest, LogicalOpcodes) {
221 char memory[kOpcodeMemory];
222 OpcodeFactory opcode_maker(memory, sizeof(memory));
224 uint32 num1 = 0x10100702;
225 ParameterSet pp_num1 = ParamPickerMake(num1);
227 PolicyOpcode* op_and1 =
228 opcode_maker.MakeOpNumberAndMatch(0, 0x00100000, kPolNone);
229 ASSERT_NE(nullptr, op_and1);
230 EXPECT_EQ(EVAL_TRUE, op_and1->Evaluate(&pp_num1, 1, NULL));
231 PolicyOpcode* op_and2 =
232 opcode_maker.MakeOpNumberAndMatch(0, 0x00000001, kPolNone);
233 ASSERT_NE(nullptr, op_and2);
234 EXPECT_EQ(EVAL_FALSE, op_and2->Evaluate(&pp_num1, 1, NULL));
237 TEST(PolicyEngineTest, WCharOpcodes1) {
238 SetupNtdllImports();
240 const wchar_t* txt1 = L"the quick fox jumps over the lazy dog";
241 const wchar_t txt2[] = L"the quick";
242 const wchar_t txt3[] = L" fox jumps";
243 const wchar_t txt4[] = L"the lazy dog";
244 const wchar_t txt5[] = L"jumps over";
245 const wchar_t txt6[] = L"g";
247 ParameterSet pp_tc1 = ParamPickerMake(txt1);
248 char memory[kOpcodeMemory];
249 OpcodeFactory opcode_maker(memory, sizeof(memory));
251 PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
252 CASE_SENSITIVE,
253 kPolNone);
254 ASSERT_NE(nullptr, op1);
256 // Simplest substring match from pos 0. It should be a successful match
257 // and the match context should be updated.
258 MatchContext mc1;
259 EXPECT_EQ(EVAL_TRUE, op1->Evaluate(&pp_tc1, 1, &mc1));
260 EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
262 // Matching again should fail and the context should be unmodified.
263 EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&pp_tc1, 1, &mc1));
264 EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
266 // Using the same match context we should continue where we left
267 // in the previous successful match,
268 PolicyOpcode* op3 = opcode_maker.MakeOpWStringMatch(0, txt3, 0,
269 CASE_SENSITIVE,
270 kPolNone);
271 ASSERT_NE(nullptr, op3);
272 EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&pp_tc1, 1, &mc1));
273 EXPECT_TRUE(_countof(txt3) + _countof(txt2) == mc1.position + 2);
275 // We now keep on matching but now we skip 6 characters which means
276 // we skip the string ' over '. And we zero the match context. This is
277 // the primitive that we use to build '??'.
278 PolicyOpcode* op4 = opcode_maker.MakeOpWStringMatch(0, txt4, 6,
279 CASE_SENSITIVE,
280 kPolClearContext);
281 ASSERT_NE(nullptr, op4);
282 EXPECT_EQ(EVAL_TRUE, op4->Evaluate(&pp_tc1, 1, &mc1));
283 EXPECT_EQ(0, mc1.position);
285 // Test that we can properly match the last part of the string
286 PolicyOpcode* op4b = opcode_maker.MakeOpWStringMatch(0, txt4, kSeekToEnd,
287 CASE_SENSITIVE,
288 kPolClearContext);
289 ASSERT_NE(nullptr, op4b);
290 EXPECT_EQ(EVAL_TRUE, op4b->Evaluate(&pp_tc1, 1, &mc1));
291 EXPECT_EQ(0, mc1.position);
293 // Test matching 'jumps over' over the entire string. This is the
294 // primitive we build '*' from.
295 PolicyOpcode* op5 = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekForward,
296 CASE_SENSITIVE, kPolNone);
297 ASSERT_NE(nullptr, op5);
298 EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&pp_tc1, 1, &mc1));
299 EXPECT_EQ(24, mc1.position);
301 // Test that we don't match because it is not at the end of the string
302 PolicyOpcode* op5b = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekToEnd,
303 CASE_SENSITIVE,
304 kPolNone);
305 ASSERT_NE(nullptr, op5b);
306 EXPECT_EQ(EVAL_FALSE, op5b->Evaluate(&pp_tc1, 1, &mc1));
307 EXPECT_EQ(24, mc1.position);
309 // Test that we function if the string does not fit. In this case we
310 // try to match 'the lazy dog' against 'he lazy dog'.
311 PolicyOpcode* op6 = opcode_maker.MakeOpWStringMatch(0, txt4, 2,
312 CASE_SENSITIVE, kPolNone);
313 ASSERT_NE(nullptr, op6);
314 EXPECT_EQ(EVAL_FALSE, op6->Evaluate(&pp_tc1, 1, &mc1));
316 // Testing matching against 'g' which should be the last char.
317 MatchContext mc2;
318 PolicyOpcode* op7 = opcode_maker.MakeOpWStringMatch(0, txt6, kSeekForward,
319 CASE_SENSITIVE, kPolNone);
320 ASSERT_NE(nullptr, op7);
321 EXPECT_EQ(EVAL_TRUE, op7->Evaluate(&pp_tc1, 1, &mc2));
322 EXPECT_EQ(37, mc2.position);
324 // Trying to match again should fail since we are in the last char.
325 // This also covers a couple of boundary conditions.
326 EXPECT_EQ(EVAL_FALSE, op7->Evaluate(&pp_tc1, 1, &mc2));
327 EXPECT_EQ(37, mc2.position);
330 TEST(PolicyEngineTest, WCharOpcodes2) {
331 SetupNtdllImports();
333 const wchar_t* path1 = L"c:\\documents and settings\\Microsoft\\BLAH.txt";
334 const wchar_t txt1[] = L"Settings\\microsoft";
335 ParameterSet pp_tc1 = ParamPickerMake(path1);
337 char memory[kOpcodeMemory];
338 OpcodeFactory opcode_maker(memory, sizeof(memory));
339 MatchContext mc1;
341 // Testing case-insensitive does not buy us much since it this option
342 // is just passed to the Microsoft API that we use normally, but just for
343 // coverage, here it is:
344 PolicyOpcode* op1s = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward,
345 CASE_SENSITIVE, kPolNone);
346 ASSERT_NE(nullptr, op1s);
347 PolicyOpcode* op1i = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward,
348 CASE_INSENSITIVE,
349 kPolNone);
350 ASSERT_NE(nullptr, op1i);
351 EXPECT_EQ(EVAL_FALSE, op1s->Evaluate(&pp_tc1, 1, &mc1));
352 EXPECT_EQ(EVAL_TRUE, op1i->Evaluate(&pp_tc1, 1, &mc1));
353 EXPECT_EQ(35, mc1.position);
356 TEST(PolicyEngineTest, ActionOpcodes) {
357 char memory[kOpcodeMemory];
358 OpcodeFactory opcode_maker(memory, sizeof(memory));
359 MatchContext mc1;
360 void* dummy = NULL;
361 ParameterSet ppb1 = ParamPickerMake(dummy);
363 PolicyOpcode* op1 = opcode_maker.MakeOpAction(ASK_BROKER, kPolNone);
364 ASSERT_NE(nullptr, op1);
365 EXPECT_TRUE(op1->IsAction());
366 EXPECT_EQ(ASK_BROKER, op1->Evaluate(&ppb1, 1, &mc1));
369 } // namespace sandbox