OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "gtest/gtest.h" | 7 #include "gtest/gtest.h" |
8 | 8 |
9 #include "native_client/src/include/nacl_compiler_annotations.h" | 9 #include "native_client/src/include/nacl_compiler_annotations.h" |
10 #include "native_client/src/shared/platform/nacl_log.h" | 10 #include "native_client/src/shared/platform/nacl_log.h" |
11 #include "native_client/src/shared/utils/types.h" | 11 #include "native_client/src/shared/utils/types.h" |
12 #include "native_client/src/trusted/validator/ncvalidate.h" | 12 #include "native_client/src/trusted/validator/ncvalidate.h" |
13 #include "native_client/src/trusted/validator/validation_cache.h" | 13 #include "native_client/src/trusted/validator/validation_cache.h" |
14 #include "native_client/src/trusted/cpu_features/arch/x86/cpu_x86.h" | 14 #include "native_client/src/trusted/cpu_features/arch/x86/cpu_x86.h" |
| 15 #include "native_client/src/trusted/validator/validation_metadata.h" |
15 | 16 |
16 #define CONTEXT_MARKER 31 | 17 #define CONTEXT_MARKER 31 |
17 #define QUERY_MARKER 37 | 18 #define QUERY_MARKER 37 |
18 | 19 |
19 #define CODE_SIZE 32 | 20 #define CODE_SIZE 32 |
20 | 21 |
21 // ret | 22 // ret |
22 const char ret[CODE_SIZE + 1] = | 23 const char ret[CODE_SIZE + 1] = |
23 "\xc3\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" | 24 "\xc3\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" |
24 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; | 25 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; |
25 | 26 |
26 // pblendw $0xc0,%xmm0,%xmm2 | 27 // pblendw $0xc0,%xmm0,%xmm2 |
27 const char sse41[CODE_SIZE + 1] = | 28 const char sse41[CODE_SIZE + 1] = |
28 "\x66\x0f\x3a\x0e\xd0\xc0\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" | 29 "\x66\x0f\x3a\x0e\xd0\xc0\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" |
29 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; | 30 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; |
30 | 31 |
31 struct MockContext { | 32 struct MockContext { |
32 int marker; /* Sanity check that we're getting the right object. */ | 33 int marker; /* Sanity check that we're getting the right object. */ |
33 int query_result; | 34 int query_result; |
| 35 int add_count_expected; |
34 bool set_validates_expected; | 36 bool set_validates_expected; |
35 bool query_destroyed; | 37 bool query_destroyed; |
36 }; | 38 }; |
37 | 39 |
38 enum MockQueryState { | 40 enum MockQueryState { |
39 QUERY_CREATED, | 41 QUERY_CREATED, |
40 QUERY_GET_CALLED, | 42 QUERY_GET_CALLED, |
41 QUERY_SET_CALLED, | 43 QUERY_SET_CALLED, |
42 QUERY_DESTROYED | 44 QUERY_DESTROYED |
43 }; | 45 }; |
(...skipping 24 matching lines...) Expand all Loading... |
68 EXPECT_EQ(QUERY_CREATED, mquery->state); | 70 EXPECT_EQ(QUERY_CREATED, mquery->state); |
69 /* Small data is suspicious. */ | 71 /* Small data is suspicious. */ |
70 EXPECT_LE((size_t) 2, length); | 72 EXPECT_LE((size_t) 2, length); |
71 mquery->add_count += 1; | 73 mquery->add_count += 1; |
72 } | 74 } |
73 | 75 |
74 int MockQueryCodeValidates(void *query) { | 76 int MockQueryCodeValidates(void *query) { |
75 MockQuery *mquery = (MockQuery *) query; | 77 MockQuery *mquery = (MockQuery *) query; |
76 EXPECT_EQ(QUERY_MARKER, mquery->marker); | 78 EXPECT_EQ(QUERY_MARKER, mquery->marker); |
77 EXPECT_EQ(QUERY_CREATED, mquery->state); | 79 EXPECT_EQ(QUERY_CREATED, mquery->state); |
78 /* Less than two pieces of data is suspicious. */ | 80 EXPECT_EQ(mquery->context->add_count_expected, mquery->add_count); |
79 EXPECT_LE(2, mquery->add_count); | |
80 mquery->state = QUERY_GET_CALLED; | 81 mquery->state = QUERY_GET_CALLED; |
81 return mquery->context->query_result; | 82 return mquery->context->query_result; |
82 } | 83 } |
83 | 84 |
84 void MockSetCodeValidates(void *query) { | 85 void MockSetCodeValidates(void *query) { |
85 MockQuery *mquery = (MockQuery *) query; | 86 MockQuery *mquery = (MockQuery *) query; |
86 ASSERT_EQ(QUERY_MARKER, mquery->marker); | 87 ASSERT_EQ(QUERY_MARKER, mquery->marker); |
87 EXPECT_EQ(QUERY_GET_CALLED, mquery->state); | 88 EXPECT_EQ(QUERY_GET_CALLED, mquery->state); |
88 EXPECT_EQ(true, mquery->context->set_validates_expected); | 89 EXPECT_EQ(true, mquery->context->set_validates_expected); |
89 mquery->state = QUERY_SET_CALLED; | 90 mquery->state = QUERY_SET_CALLED; |
90 } | 91 } |
91 | 92 |
92 void MockDestroyQuery(void *query) { | 93 void MockDestroyQuery(void *query) { |
93 MockQuery *mquery = (MockQuery *) query; | 94 MockQuery *mquery = (MockQuery *) query; |
94 ASSERT_EQ(QUERY_MARKER, mquery->marker); | 95 ASSERT_EQ(QUERY_MARKER, mquery->marker); |
95 if (mquery->context->set_validates_expected) { | 96 if (mquery->context->set_validates_expected) { |
96 EXPECT_EQ(QUERY_SET_CALLED, mquery->state); | 97 EXPECT_EQ(QUERY_SET_CALLED, mquery->state); |
97 } else { | 98 } else { |
98 EXPECT_EQ(QUERY_GET_CALLED, mquery->state); | 99 EXPECT_EQ(QUERY_GET_CALLED, mquery->state); |
99 } | 100 } |
100 mquery->state = QUERY_DESTROYED; | 101 mquery->state = QUERY_DESTROYED; |
101 mquery->context->query_destroyed = true; | 102 mquery->context->query_destroyed = true; |
102 free(mquery); | 103 free(mquery); |
103 } | 104 } |
104 | 105 |
105 class ValidationCachingInterfaceTests : public ::testing::Test { | 106 class ValidationCachingInterfaceTests : public ::testing::Test { |
106 protected: | 107 protected: |
107 MockContext context; | 108 MockContext context; |
| 109 NaClValidationMetadata *metadata_ptr; |
108 NaClValidationCache cache; | 110 NaClValidationCache cache; |
109 const struct NaClValidatorInterface *validator; | 111 const struct NaClValidatorInterface *validator; |
110 NaClCPUFeatures *cpu_features; | 112 NaClCPUFeatures *cpu_features; |
111 | 113 |
112 unsigned char code_buffer[CODE_SIZE]; | 114 unsigned char code_buffer[CODE_SIZE]; |
113 | 115 |
114 void SetUp() { | 116 void SetUp() { |
115 context.marker = CONTEXT_MARKER; | 117 context.marker = CONTEXT_MARKER; |
116 context.query_result = 1; | 118 context.query_result = 1; |
| 119 context.add_count_expected = 4; |
117 context.set_validates_expected = false; | 120 context.set_validates_expected = false; |
118 context.query_destroyed = false; | 121 context.query_destroyed = false; |
119 | 122 |
| 123 metadata_ptr = NULL; |
| 124 |
120 cache.handle = &context; | 125 cache.handle = &context; |
121 cache.CreateQuery = MockCreateQuery; | 126 cache.CreateQuery = MockCreateQuery; |
122 cache.AddData = MockAddData; | 127 cache.AddData = MockAddData; |
123 cache.QueryKnownToValidate = MockQueryCodeValidates; | 128 cache.QueryKnownToValidate = MockQueryCodeValidates; |
124 cache.SetKnownToValidate = MockSetCodeValidates; | 129 cache.SetKnownToValidate = MockSetCodeValidates; |
125 cache.DestroyQuery = MockDestroyQuery; | 130 cache.DestroyQuery = MockDestroyQuery; |
126 | 131 |
127 validator = NaClCreateValidator(); | 132 validator = NaClCreateValidator(); |
128 cpu_features = (NaClCPUFeatures *) malloc(validator->CPUFeatureSize); | 133 cpu_features = (NaClCPUFeatures *) malloc(validator->CPUFeatureSize); |
129 EXPECT_NE(cpu_features, (NaClCPUFeatures *) NULL); | 134 EXPECT_NE(cpu_features, (NaClCPUFeatures *) NULL); |
130 validator->SetAllCPUFeatures(cpu_features); | 135 validator->SetAllCPUFeatures(cpu_features); |
131 | 136 |
132 memset(code_buffer, 0x90, sizeof(code_buffer)); | 137 memset(code_buffer, 0x90, sizeof(code_buffer)); |
133 } | 138 } |
134 | 139 |
135 NaClValidationStatus Validate() { | 140 NaClValidationStatus Validate() { |
136 return validator->Validate(0, code_buffer, 32, | 141 return validator->Validate(0, code_buffer, 32, |
137 FALSE, /* stubout_mode */ | 142 FALSE, /* stubout_mode */ |
138 FALSE, /* readonly_test */ | 143 FALSE, /* readonly_test */ |
139 cpu_features, | 144 cpu_features, |
| 145 metadata_ptr, |
140 &cache); | 146 &cache); |
141 } | 147 } |
142 | 148 |
143 void TearDown() { | 149 void TearDown() { |
144 free(cpu_features); | 150 free(cpu_features); |
145 } | 151 } |
146 }; | 152 }; |
147 | 153 |
148 TEST_F(ValidationCachingInterfaceTests, Sanity) { | 154 TEST_F(ValidationCachingInterfaceTests, Sanity) { |
149 void *query = cache.CreateQuery(cache.handle); | 155 void *query = cache.CreateQuery(cache.handle); |
| 156 context.add_count_expected = 2; |
150 cache.AddData(query, NULL, 6); | 157 cache.AddData(query, NULL, 6); |
151 cache.AddData(query, NULL, 128); | 158 cache.AddData(query, NULL, 128); |
152 EXPECT_EQ(1, cache.QueryKnownToValidate(query)); | 159 EXPECT_EQ(1, cache.QueryKnownToValidate(query)); |
153 cache.DestroyQuery(query); | 160 cache.DestroyQuery(query); |
154 EXPECT_EQ(true, context.query_destroyed); | 161 EXPECT_EQ(true, context.query_destroyed); |
155 } | 162 } |
156 | 163 |
157 TEST_F(ValidationCachingInterfaceTests, NoCache) { | 164 TEST_F(ValidationCachingInterfaceTests, NoCache) { |
158 const struct NaClValidatorInterface *validator = NaClCreateValidator(); | 165 const struct NaClValidatorInterface *validator = NaClCreateValidator(); |
159 NaClValidationStatus status = validator->Validate( | 166 NaClValidationStatus status = validator->Validate( |
160 0, code_buffer, CODE_SIZE, | 167 0, code_buffer, CODE_SIZE, |
161 FALSE, /* stubout_mode */ | 168 FALSE, /* stubout_mode */ |
162 FALSE, /* readonly_test */ | 169 FALSE, /* readonly_test */ |
163 cpu_features, | 170 cpu_features, |
| 171 NULL, /* metadata */ |
164 NULL); | 172 NULL); |
165 EXPECT_EQ(NaClValidationSucceeded, status); | 173 EXPECT_EQ(NaClValidationSucceeded, status); |
166 } | 174 } |
167 | 175 |
168 TEST_F(ValidationCachingInterfaceTests, CacheHit) { | 176 TEST_F(ValidationCachingInterfaceTests, CacheHit) { |
169 NaClValidationStatus status = Validate(); | 177 NaClValidationStatus status = Validate(); |
170 EXPECT_EQ(NaClValidationSucceeded, status); | 178 EXPECT_EQ(NaClValidationSucceeded, status); |
171 EXPECT_EQ(true, context.query_destroyed); | 179 EXPECT_EQ(true, context.query_destroyed); |
172 } | 180 } |
173 | 181 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 } | 216 } |
209 | 217 |
210 TEST_F(ValidationCachingInterfaceTests, IllegalCacheHit) { | 218 TEST_F(ValidationCachingInterfaceTests, IllegalCacheHit) { |
211 memcpy(code_buffer, ret, CODE_SIZE); | 219 memcpy(code_buffer, ret, CODE_SIZE); |
212 NaClValidationStatus status = Validate(); | 220 NaClValidationStatus status = Validate(); |
213 // Success proves the cache shortcircuted validation. | 221 // Success proves the cache shortcircuted validation. |
214 EXPECT_EQ(NaClValidationSucceeded, status); | 222 EXPECT_EQ(NaClValidationSucceeded, status); |
215 EXPECT_EQ(true, context.query_destroyed); | 223 EXPECT_EQ(true, context.query_destroyed); |
216 } | 224 } |
217 | 225 |
| 226 TEST_F(ValidationCachingInterfaceTests, Metadata) { |
| 227 NaClValidationMetadata metadata; |
| 228 memset(&metadata, 0, sizeof(metadata)); |
| 229 metadata.identity_type = NaClCodeIdentityFile; |
| 230 metadata.file_name = "foobar"; |
| 231 metadata.file_name_length = strlen(metadata.file_name); |
| 232 metadata.file_size = CODE_SIZE; |
| 233 metadata.mtime = 100; |
| 234 metadata_ptr = &metadata; |
| 235 context.add_count_expected = 8; |
| 236 NaClValidationStatus status = Validate(); |
| 237 EXPECT_EQ(NaClValidationSucceeded, status); |
| 238 EXPECT_EQ(true, context.query_destroyed); |
| 239 } |
| 240 |
218 // Test driver function. | 241 // Test driver function. |
219 int main(int argc, char *argv[]) { | 242 int main(int argc, char *argv[]) { |
220 // The IllegalInst test touches the log mutex deep inside the validator. | 243 // The IllegalInst test touches the log mutex deep inside the validator. |
221 // This causes an SEH exception to be thrown on Windows if the mutex is not | 244 // This causes an SEH exception to be thrown on Windows if the mutex is not |
222 // initialized. | 245 // initialized. |
223 // http://code.google.com/p/nativeclient/issues/detail?id=1696 | 246 // http://code.google.com/p/nativeclient/issues/detail?id=1696 |
224 NaClLogModuleInit(); | 247 NaClLogModuleInit(); |
225 testing::InitGoogleTest(&argc, argv); | 248 testing::InitGoogleTest(&argc, argv); |
226 return RUN_ALL_TESTS(); | 249 return RUN_ALL_TESTS(); |
227 } | 250 } |
OLD | NEW |