Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: mojo/public/cpp/bindings/lib/array_internal.h

Issue 466613002: Add validation logic for non-nullable types. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | mojo/public/cpp/bindings/lib/array_internal.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
7 7
8 #include <new> 8 #include <new>
9 #include <vector> 9 #include <vector>
10 10
11 #include "mojo/public/c/system/macros.h"
11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
12 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" 13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
13 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" 14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
14 #include "mojo/public/cpp/bindings/lib/buffer.h" 15 #include "mojo/public/cpp/bindings/lib/buffer.h"
16 #include "mojo/public/cpp/bindings/lib/template_util.h"
15 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
16 #include "mojo/public/cpp/environment/logging.h" 18 #include "mojo/public/cpp/environment/logging.h"
17 19
18 namespace mojo { 20 namespace mojo {
19 template <typename T> class Array; 21 template <typename T> class Array;
20 class String; 22 class String;
21 23
22 namespace internal { 24 namespace internal {
23 25
24 template <typename T> 26 template <typename T>
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 return ((num_elements + 7) / 8); 105 return ((num_elements + 7) / 8);
104 } 106 }
105 static BitRef ToRef(StorageType* storage, size_t offset) { 107 static BitRef ToRef(StorageType* storage, size_t offset) {
106 return BitRef(&storage[offset / 8], 1 << (offset % 8)); 108 return BitRef(&storage[offset / 8], 1 << (offset % 8));
107 } 109 }
108 static bool ToConstRef(const StorageType* storage, size_t offset) { 110 static bool ToConstRef(const StorageType* storage, size_t offset) {
109 return (storage[offset / 8] & (1 << (offset % 8))) != 0; 111 return (storage[offset / 8] & (1 << (offset % 8))) != 0;
110 } 112 }
111 }; 113 };
112 114
115 // Array type information needed for valdiation.
116 template <uint32_t in_expected_num_elements,
117 bool in_element_nullable,
118 typename InElementValidateParams>
119 class ArrayValidateParams {
120 public:
121 // Validation information for elements. It is either another specialization of
122 // ArrayValidateParams (if elements are arrays) or NoValidateParams.
123 typedef InElementValidateParams ElementValidateParams;
124
125 // If |expected_num_elements| is not 0, the array is expected to have exactly
126 // that number of elements.
127 static const uint32_t expected_num_elements = in_expected_num_elements;
128 // Whether the elements are nullable.
129 static const bool element_nullable = in_element_nullable;
130 };
131
132 // NoValidateParams is used to indicate the end of an ArrayValidateParams chain.
133 class NoValidateParams {
134 };
135
113 // What follows is code to support the serialization of Array_Data<T>. There 136 // What follows is code to support the serialization of Array_Data<T>. There
114 // are two interesting cases: arrays of primitives and arrays of objects. 137 // are two interesting cases: arrays of primitives and arrays of objects.
115 // Arrays of objects are represented as arrays of pointers to objects. 138 // Arrays of objects are represented as arrays of pointers to objects.
116 139
117 template <typename T, bool kIsHandle> struct ArraySerializationHelper; 140 template <typename T, bool is_handle> struct ArraySerializationHelper;
118 141
119 template <typename T> 142 template <typename T>
120 struct ArraySerializationHelper<T, false> { 143 struct ArraySerializationHelper<T, false> {
121 typedef typename ArrayDataTraits<T>::StorageType ElementType; 144 typedef typename ArrayDataTraits<T>::StorageType ElementType;
122 145
123 static void EncodePointersAndHandles(const ArrayHeader* header, 146 static void EncodePointersAndHandles(const ArrayHeader* header,
124 ElementType* elements, 147 ElementType* elements,
125 std::vector<Handle>* handles) { 148 std::vector<Handle>* handles) {
126 } 149 }
127 150
128 static void DecodePointersAndHandles(const ArrayHeader* header, 151 static void DecodePointersAndHandles(const ArrayHeader* header,
129 ElementType* elements, 152 ElementType* elements,
130 std::vector<Handle>* handles) { 153 std::vector<Handle>* handles) {
131 } 154 }
132 155
156 template <bool element_nullable, typename ElementValidateParams>
133 static bool ValidateElements(const ArrayHeader* header, 157 static bool ValidateElements(const ArrayHeader* header,
134 const ElementType* elements, 158 const ElementType* elements,
135 BoundsChecker* bounds_checker) { 159 BoundsChecker* bounds_checker) {
160 MOJO_COMPILE_ASSERT(!element_nullable,
161 Primitive_type_should_be_non_nullable);
162 MOJO_COMPILE_ASSERT(
163 (IsSame<ElementValidateParams, NoValidateParams>::value),
164 Primitive_type_should_not_have_array_validate_params);
136 return true; 165 return true;
137 } 166 }
138 }; 167 };
139 168
140 template <> 169 template <>
141 struct ArraySerializationHelper<Handle, true> { 170 struct ArraySerializationHelper<Handle, true> {
142 typedef ArrayDataTraits<Handle>::StorageType ElementType; 171 typedef ArrayDataTraits<Handle>::StorageType ElementType;
143 172
144 static void EncodePointersAndHandles(const ArrayHeader* header, 173 static void EncodePointersAndHandles(const ArrayHeader* header,
145 ElementType* elements, 174 ElementType* elements,
146 std::vector<Handle>* handles); 175 std::vector<Handle>* handles);
147 176
148 static void DecodePointersAndHandles(const ArrayHeader* header, 177 static void DecodePointersAndHandles(const ArrayHeader* header,
149 ElementType* elements, 178 ElementType* elements,
150 std::vector<Handle>* handles); 179 std::vector<Handle>* handles);
151 180
181 template <bool element_nullable, typename ElementValidateParams>
152 static bool ValidateElements(const ArrayHeader* header, 182 static bool ValidateElements(const ArrayHeader* header,
153 const ElementType* elements, 183 const ElementType* elements,
154 BoundsChecker* bounds_checker); 184 BoundsChecker* bounds_checker) {
185 MOJO_COMPILE_ASSERT(
186 (IsSame<ElementValidateParams, NoValidateParams>::value),
187 Handle_type_should_not_have_array_validate_params);
188
189 for (uint32_t i = 0; i < header->num_elements; ++i) {
190 if (IsNonNullableValidationEnabled() && !element_nullable &&
191 elements[i].value() == kEncodedInvalidHandleValue) {
192 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE);
193 return false;
194 }
195 if (!bounds_checker->ClaimHandle(elements[i])) {
196 ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE);
197 return false;
198 }
199 }
200 return true;
201 }
155 }; 202 };
156 203
157 template <typename H> 204 template <typename H>
158 struct ArraySerializationHelper<H, true> { 205 struct ArraySerializationHelper<H, true> {
159 typedef typename ArrayDataTraits<H>::StorageType ElementType; 206 typedef typename ArrayDataTraits<H>::StorageType ElementType;
160 207
161 static void EncodePointersAndHandles(const ArrayHeader* header, 208 static void EncodePointersAndHandles(const ArrayHeader* header,
162 ElementType* elements, 209 ElementType* elements,
163 std::vector<Handle>* handles) { 210 std::vector<Handle>* handles) {
164 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( 211 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles(
165 header, elements, handles); 212 header, elements, handles);
166 } 213 }
167 214
168 static void DecodePointersAndHandles(const ArrayHeader* header, 215 static void DecodePointersAndHandles(const ArrayHeader* header,
169 ElementType* elements, 216 ElementType* elements,
170 std::vector<Handle>* handles) { 217 std::vector<Handle>* handles) {
171 ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( 218 ArraySerializationHelper<Handle, true>::DecodePointersAndHandles(
172 header, elements, handles); 219 header, elements, handles);
173 } 220 }
174 221
222 template <bool element_nullable, typename ElementValidateParams>
175 static bool ValidateElements(const ArrayHeader* header, 223 static bool ValidateElements(const ArrayHeader* header,
176 const ElementType* elements, 224 const ElementType* elements,
177 BoundsChecker* bounds_checker) { 225 BoundsChecker* bounds_checker) {
178 return ArraySerializationHelper<Handle, true>::ValidateElements( 226 return ArraySerializationHelper<Handle, true>::
179 header, elements, bounds_checker); 227 ValidateElements<element_nullable, ElementValidateParams>(
228 header, elements, bounds_checker);
180 } 229 }
181 }; 230 };
182 231
183 template <typename P> 232 template <typename P>
184 struct ArraySerializationHelper<P*, false> { 233 struct ArraySerializationHelper<P*, false> {
185 typedef typename ArrayDataTraits<P*>::StorageType ElementType; 234 typedef typename ArrayDataTraits<P*>::StorageType ElementType;
186 235
187 static void EncodePointersAndHandles(const ArrayHeader* header, 236 static void EncodePointersAndHandles(const ArrayHeader* header,
188 ElementType* elements, 237 ElementType* elements,
189 std::vector<Handle>* handles) { 238 std::vector<Handle>* handles) {
190 for (uint32_t i = 0; i < header->num_elements; ++i) 239 for (uint32_t i = 0; i < header->num_elements; ++i)
191 Encode(&elements[i], handles); 240 Encode(&elements[i], handles);
192 } 241 }
193 242
194 static void DecodePointersAndHandles(const ArrayHeader* header, 243 static void DecodePointersAndHandles(const ArrayHeader* header,
195 ElementType* elements, 244 ElementType* elements,
196 std::vector<Handle>* handles) { 245 std::vector<Handle>* handles) {
197 for (uint32_t i = 0; i < header->num_elements; ++i) 246 for (uint32_t i = 0; i < header->num_elements; ++i)
198 Decode(&elements[i], handles); 247 Decode(&elements[i], handles);
199 } 248 }
200 249
250 template <bool element_nullable, typename ElementValidateParams>
201 static bool ValidateElements(const ArrayHeader* header, 251 static bool ValidateElements(const ArrayHeader* header,
202 const ElementType* elements, 252 const ElementType* elements,
203 BoundsChecker* bounds_checker) { 253 BoundsChecker* bounds_checker) {
204 for (uint32_t i = 0; i < header->num_elements; ++i) { 254 for (uint32_t i = 0; i < header->num_elements; ++i) {
255 if (IsNonNullableValidationEnabled() && !element_nullable &&
256 !elements[i].offset) {
257 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
258 return false;
259 }
205 if (!ValidateEncodedPointer(&elements[i].offset)) { 260 if (!ValidateEncodedPointer(&elements[i].offset)) {
206 ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); 261 ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER);
207 return false; 262 return false;
208 } 263 }
209 if (!P::Validate(DecodePointerRaw(&elements[i].offset), bounds_checker)) 264 if (!ValidateCaller<P, ElementValidateParams>::Run(
265 DecodePointerRaw(&elements[i].offset), bounds_checker)) {
210 return false; 266 return false;
267 }
211 } 268 }
212 return true; 269 return true;
213 } 270 }
271
272 private:
273 template <typename T, typename Params>
274 struct ValidateCaller {
275 static bool Run(const void* data, BoundsChecker* bounds_checker) {
276 MOJO_COMPILE_ASSERT(
277 (IsSame<Params, NoValidateParams>::value),
278 Struct_type_should_not_have_array_validate_params);
279
280 return T::Validate(data, bounds_checker);
281 }
282 };
283
284 template <typename T, typename Params>
285 struct ValidateCaller<Array_Data<T>, Params> {
286 static bool Run(const void* data, BoundsChecker* bounds_checker) {
287 return Array_Data<T>::template Validate<Params>(data, bounds_checker);
288 }
289 };
214 }; 290 };
215 291
216 template <typename T> 292 template <typename T>
217 class Array_Data { 293 class Array_Data {
218 public: 294 public:
219 typedef ArrayDataTraits<T> Traits; 295 typedef ArrayDataTraits<T> Traits;
220 typedef typename Traits::StorageType StorageType; 296 typedef typename Traits::StorageType StorageType;
221 typedef typename Traits::Ref Ref; 297 typedef typename Traits::Ref Ref;
222 typedef typename Traits::ConstRef ConstRef; 298 typedef typename Traits::ConstRef ConstRef;
223 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; 299 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper;
224 300
225 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { 301 static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
226 size_t num_bytes = sizeof(Array_Data<T>) + 302 size_t num_bytes = sizeof(Array_Data<T>) +
227 Traits::GetStorageSize(num_elements); 303 Traits::GetStorageSize(num_elements);
228 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, 304 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes,
229 num_elements); 305 num_elements);
230 } 306 }
231 307
232 // If expected_num_elements is not zero, the actual number of elements in the 308 template <typename Params>
233 // header must match that value or the message is rejected. 309 static bool Validate(const void* data, BoundsChecker* bounds_checker) {
234 static bool Validate(const void* data,
235 BoundsChecker* bounds_checker,
236 uint32_t expected_num_elements = 0) {
237 if (!data) 310 if (!data)
238 return true; 311 return true;
239 if (!IsAligned(data)) { 312 if (!IsAligned(data)) {
240 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); 313 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT);
241 return false; 314 return false;
242 } 315 }
243 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { 316 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) {
244 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 317 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
245 return false; 318 return false;
246 } 319 }
247 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); 320 const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
248 if (header->num_bytes < (sizeof(Array_Data<T>) + 321 if (header->num_bytes < (sizeof(Array_Data<T>) +
249 Traits::GetStorageSize(header->num_elements))) { 322 Traits::GetStorageSize(header->num_elements))) {
250 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); 323 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
251 return false; 324 return false;
252 } 325 }
253 if (expected_num_elements != 0 && 326 if (Params::expected_num_elements != 0 &&
254 header->num_elements != expected_num_elements) { 327 header->num_elements != Params::expected_num_elements) {
255 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); 328 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
256 return false; 329 return false;
257 } 330 }
258 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { 331 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) {
259 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 332 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
260 return false; 333 return false;
261 } 334 }
262 335
263 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); 336 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
264 return Helper::ValidateElements(&object->header_, object->storage(), 337 return Helper::template ValidateElements<
265 bounds_checker); 338 Params::element_nullable, typename Params::ElementValidateParams>(
339 &object->header_, object->storage(), bounds_checker);
266 } 340 }
267 341
268 size_t size() const { return header_.num_elements; } 342 size_t size() const { return header_.num_elements; }
269 343
270 Ref at(size_t offset) { 344 Ref at(size_t offset) {
271 MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements)); 345 MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements));
272 return Traits::ToRef(storage(), offset); 346 return Traits::ToRef(storage(), offset);
273 } 347 }
274 348
275 ConstRef at(size_t offset) const { 349 ConstRef at(size_t offset) const {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 }; 459 };
386 460
387 template <> struct WrapperTraits<String, false> { 461 template <> struct WrapperTraits<String, false> {
388 typedef String_Data* DataType; 462 typedef String_Data* DataType;
389 }; 463 };
390 464
391 } // namespace internal 465 } // namespace internal
392 } // namespace mojo 466 } // namespace mojo
393 467
394 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 468 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
OLDNEW
« no previous file with comments | « no previous file | mojo/public/cpp/bindings/lib/array_internal.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698