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

Side by Side Diff: ppapi/native_client/src/shared/ppapi_proxy/object_serialize.cc

Issue 9022021: Proxy PPB_ArrayBuffer_Dev, make them work over Messaging (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add testing for multiple sizes of array. Created 8 years, 11 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 * Copyright (c) 2011 The Chromium 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 "native_client/src/shared/ppapi_proxy/object_serialize.h" 7 #include "native_client/src/shared/ppapi_proxy/object_serialize.h"
8 8
9 #include <limits> 9 #include <limits>
10 #include <stdio.h> 10 #include <stdio.h>
(...skipping 24 matching lines...) Expand all
35 35
36 // The basic serialization structure. Used alone for PP_VARTYPE_VOID, 36 // The basic serialization structure. Used alone for PP_VARTYPE_VOID,
37 // PP_VARTYPE_NULL, and PP_VARTYPE_INT32. 37 // PP_VARTYPE_NULL, and PP_VARTYPE_INT32.
38 struct SerializedFixed { 38 struct SerializedFixed {
39 uint32_t type; 39 uint32_t type;
40 union { 40 union {
41 // PP_VARTYPE_BOOLEAN uses this. 41 // PP_VARTYPE_BOOLEAN uses this.
42 bool boolean_value; 42 bool boolean_value;
43 // PP_VARTYPE_INT32 uses this. 43 // PP_VARTYPE_INT32 uses this.
44 int32_t int32_value; 44 int32_t int32_value;
45 // PP_VARTYPE_STRING uses this. 45 // PP_VARTYPE_STRING and PP_VARTYPE_ARRAY_BUFFER use this.
46 uint32_t string_length; 46 uint32_t string_length;
47 } u; 47 } u;
48 // The size of this structure should be 8 bytes on all platforms. 48 // The size of this structure should be 8 bytes on all platforms.
49 }; 49 };
50 50
51 // The structure used for PP_VARTYPE_DOUBLE. 51 // The structure used for PP_VARTYPE_DOUBLE.
52 struct SerializedDouble { 52 struct SerializedDouble {
53 struct SerializedFixed fixed; 53 struct SerializedFixed fixed;
54 double double_value; 54 double double_value;
55 }; 55 };
56 56
57 // The structure used for PP_VARTYPE_STRING. 57 // The structure used for PP_VARTYPE_STRING and PP_VARTYPE_ARRAYBUFFER.
58
59 struct SerializedString { 58 struct SerializedString {
60 struct SerializedFixed fixed; 59 struct SerializedFixed fixed;
61 char string_bytes[kStringFixedBytes]; 60 char string_bytes[kStringFixedBytes];
62 // Any remaining characters immediately follow, and are padded out to the 61 // Any remaining characters immediately follow, and are padded out to the
63 // nearest multiple of kStringRoundBase bytes. 62 // nearest multiple of kStringRoundBase bytes.
64 }; 63 };
65 64
66 // TODO(sehr): Add a more general compile time assertion package elsewhere. 65 // TODO(sehr): Add a more general compile time assertion package elsewhere.
67 #define ASSERT_TYPE_SIZE(struct_name, struct_size) \ 66 #define ASSERT_TYPE_SIZE(struct_name, struct_size) \
68 int struct_name##_size_should_be_##struct_size[ \ 67 int struct_name##_size_should_be_##struct_size[ \
69 sizeof(struct_name) == struct_size ? 1 : 0] 68 sizeof(struct_name) == struct_size ? 1 : 0]
70 69
71 // Check the wire format sizes for the PP_Var subtypes. 70 // Check the wire format sizes for the PP_Var subtypes.
72 ASSERT_TYPE_SIZE(SerializedFixed, 8); 71 ASSERT_TYPE_SIZE(SerializedFixed, 8);
73 ASSERT_TYPE_SIZE(SerializedDouble, 16); 72 ASSERT_TYPE_SIZE(SerializedDouble, 16);
74 ASSERT_TYPE_SIZE(SerializedString, 16); 73 ASSERT_TYPE_SIZE(SerializedString, 16);
74 // IMPORTANT NOTE: SerializePpVar below assumes these sizes are multiples of 8,
75 // otherwise the reinterpret_casts could cause alignment issues. New SerializedX
76 // types should also be multiples of 8 bytes, or the SerializePpVar function
77 // must be updated to enforce appropriate alignment.
75 78
76 // 79 //
77 // We currently use offsetof to find the start of string storage. 80 // We currently use offsetof to find the start of string storage.
78 // This avoids the (never seen) case where the compiler inserts in 81 // This avoids the (never seen) case where the compiler inserts in
79 // padding between the struct SerializedFixed fixed header and the 82 // padding between the struct SerializedFixed fixed header and the
80 // actual payload value in the double, string, and object 83 // actual payload value in the double, string, and object
81 // serialization variants. 84 // serialization variants.
82 // 85 //
83 // Untrusted arm toolchain defines an offsetof in stddef.h, so we have 86 // Untrusted arm toolchain defines an offsetof in stddef.h, so we have
84 // to prefix. 87 // to prefix.
85 // 88 //
86 #define NACL_OFFSETOF(pod_t, member) \ 89 #define NACL_OFFSETOF(pod_t, member) \
87 (static_cast<size_t>(reinterpret_cast<uintptr_t>(&((pod_t *) NULL)->member))) 90 (static_cast<size_t>(reinterpret_cast<uintptr_t>(&((pod_t *) NULL)->member)))
88 91
89 namespace { 92 namespace {
90 93
91 // Adding value1 and value2 would overflow a uint32_t. 94 // Adding value1 and value2 would overflow a uint32_t.
92 bool AddWouldOverflow(size_t value1, size_t value2) { 95 bool AddWouldOverflow(size_t value1, size_t value2) {
93 if (value1 > std::numeric_limits<size_t>::max() - value2) { 96 if (value1 > std::numeric_limits<size_t>::max() - value2) {
94 return true; 97 return true;
95 } 98 }
96 size_t sum = value1 + value2; 99 uint64_t sum = uint64_t(value1) + value2;
dmichael (off chromium) 2011/12/27 22:20:47 size_t is 32-bit in NaCl and the 32-bit trusted bu
97 return sum > std::numeric_limits<uint32_t>::max(); 100 return sum > std::numeric_limits<uint32_t>::max();
98 } 101 }
99 102
100 uint32_t RoundedStringBytes(uint32_t string_length) { 103 uint32_t RoundedStringBytes(uint32_t string_length) {
101 // Compute the string length, padded to the nearest multiple of 8. 104 // Compute the string length, padded to the nearest multiple of 8.
102 if (AddWouldOverflow(string_length, kStringRoundBase - 1)) { 105 if (AddWouldOverflow(string_length, kStringRoundBase - 1)) {
103 return std::numeric_limits<uint32_t>::max(); 106 return std::numeric_limits<uint32_t>::max();
104 } 107 }
105 return (string_length + (kStringRoundBase - 1)) & ~(kStringRoundBase - 1); 108 return (string_length + (kStringRoundBase - 1)) & ~(kStringRoundBase - 1);
106 } 109 }
107 110
108 uint32_t PpVarSize(const PP_Var& var) { 111 uint32_t PpVarSize(const PP_Var& var) {
109 switch (var.type) { 112 switch (var.type) {
110 case PP_VARTYPE_UNDEFINED: 113 case PP_VARTYPE_UNDEFINED:
111 case PP_VARTYPE_NULL: 114 case PP_VARTYPE_NULL:
112 case PP_VARTYPE_BOOL: 115 case PP_VARTYPE_BOOL:
113 case PP_VARTYPE_INT32: 116 case PP_VARTYPE_INT32:
114 return sizeof(SerializedFixed); 117 return sizeof(SerializedFixed);
115 case PP_VARTYPE_DOUBLE: 118 case PP_VARTYPE_DOUBLE:
116 return sizeof(SerializedDouble); 119 return sizeof(SerializedDouble);
117 case PP_VARTYPE_STRING: { 120 case PP_VARTYPE_STRING: {
118 uint32_t string_length; 121 uint32_t string_length;
119 (void) PPBVarInterface()->VarToUtf8(var, &string_length); 122 (void) PPBVarInterface()->VarToUtf8(var, &string_length);
120 string_length = RoundedStringBytes(string_length); 123 string_length = RoundedStringBytes(string_length);
121 if (std::numeric_limits<uint32_t>::max() == string_length || 124 if (AddWouldOverflow(string_length,
dmichael (off chromium) 2011/12/27 22:20:47 And this part doesn't seem necessary if AddWouldOv
122 AddWouldOverflow(string_length,
123 NACL_OFFSETOF(SerializedString, string_bytes))) { 125 NACL_OFFSETOF(SerializedString, string_bytes))) {
124 // Adding the length to the fixed portion would overflow. 126 // Adding the length to the fixed portion would overflow.
125 return 0; 127 return 0;
126 } 128 }
127 return static_cast<uint32_t>(NACL_OFFSETOF(SerializedString, string_bytes) 129 return static_cast<uint32_t>(NACL_OFFSETOF(SerializedString, string_bytes)
128 + string_length); 130 + string_length);
129 break; 131 break;
130 } 132 }
133 case PP_VARTYPE_ARRAY_BUFFER: {
134 uint32_t buffer_length = PPBVarArrayBufferInterface()->ByteLength(var);
135 buffer_length = RoundedStringBytes(buffer_length);
136 if (AddWouldOverflow(buffer_length,
137 NACL_OFFSETOF(SerializedString, string_bytes))) {
138 // Adding the length to the fixed portion would overflow.
139 return 0;
140 }
141 return static_cast<uint32_t>(NACL_OFFSETOF(SerializedString, string_bytes)
142 + buffer_length);
143 break;
144 }
131 case PP_VARTYPE_OBJECT: 145 case PP_VARTYPE_OBJECT:
132 case PP_VARTYPE_ARRAY: 146 case PP_VARTYPE_ARRAY:
133 case PP_VARTYPE_DICTIONARY: 147 case PP_VARTYPE_DICTIONARY:
134 case PP_VARTYPE_ARRAY_BUFFER:
135 NACL_NOTREACHED(); 148 NACL_NOTREACHED();
136 break; 149 break;
137 } 150 }
138 // Unrecognized type. 151 // Unrecognized type.
139 return 0; 152 return 0;
140 } 153 }
141 154
142 uint32_t PpVarVectorSize(const PP_Var* vars, uint32_t argc) { 155 uint32_t PpVarVectorSize(const PP_Var* vars, uint32_t argc) {
143 size_t size = 0; 156 size_t size = 0;
144 157
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 memcpy(reinterpret_cast<void*>(ss->string_bytes), 219 memcpy(reinterpret_cast<void*>(ss->string_bytes),
207 reinterpret_cast<const void*>(str), 220 reinterpret_cast<const void*>(str),
208 string_length); 221 string_length);
209 // Fill padding bytes with zeros. 222 // Fill padding bytes with zeros.
210 memset(reinterpret_cast<void*>(ss->string_bytes + string_length), 0, 223 memset(reinterpret_cast<void*>(ss->string_bytes + string_length), 0,
211 RoundedStringBytes(string_length) - string_length); 224 RoundedStringBytes(string_length) - string_length);
212 element_size = NACL_OFFSETOF(SerializedString, string_bytes) 225 element_size = NACL_OFFSETOF(SerializedString, string_bytes)
213 + RoundedStringBytes(string_length); 226 + RoundedStringBytes(string_length);
214 break; 227 break;
215 } 228 }
229 case PP_VARTYPE_ARRAY_BUFFER: {
230 uint32_t buffer_length =
231 PPBVarArrayBufferInterface()->ByteLength(vars[i]);
232 SerializedString* ss = reinterpret_cast<SerializedString*>(p);
233 ss->fixed.u.string_length = buffer_length;
234 memcpy(reinterpret_cast<void*>(ss->string_bytes),
235 PPBVarArrayBufferInterface()->Map(vars[i]),
236 buffer_length);
237 // Fill padding bytes with zeros.
238 memset(reinterpret_cast<void*>(ss->string_bytes + buffer_length), 0,
239 RoundedStringBytes(buffer_length) - buffer_length);
240 element_size = NACL_OFFSETOF(SerializedString, string_bytes)
241 + RoundedStringBytes(buffer_length);
242 break;
243 }
216 case PP_VARTYPE_OBJECT: 244 case PP_VARTYPE_OBJECT:
217 case PP_VARTYPE_ARRAY: 245 case PP_VARTYPE_ARRAY:
218 case PP_VARTYPE_DICTIONARY: 246 case PP_VARTYPE_DICTIONARY:
219 case PP_VARTYPE_ARRAY_BUFFER:
220 NACL_NOTREACHED(); 247 NACL_NOTREACHED();
221 default: 248 default:
222 return false; 249 return false;
223 } 250 }
224 offset += element_size; 251 offset += element_size;
225 } 252 }
226 return true; 253 return true;
227 } 254 }
228 255
229 256
230 // 257 //
231 // Compute how many bytes does the string object to be deserialzed use 258 // Compute how many bytes does the string object to be deserialzed use
232 // in the serialized format. On error, return 259 // in the serialized format. On error, return
233 // std::numeric_limits<uint32_t>::max(). This means we cannot handle 260 // std::numeric_limits<uint32_t>::max(). This means we cannot handle
234 // 2**32-1 byte strings. 261 // 2**32-1 byte strings.
235 // 262 //
236 uint32_t DeserializeStringSize(char* p, uint32_t length) { 263 uint32_t DeserializeStringSize(char* p, uint32_t length) {
237 // zero length strings are okay... but not shorter 264 // zero length strings are okay... but not shorter
238 if (length < NACL_OFFSETOF(SerializedString, string_bytes)) { 265 if (length < NACL_OFFSETOF(SerializedString, string_bytes)) {
239 return std::numeric_limits<uint32_t>::max(); 266 return std::numeric_limits<uint32_t>::max();
240 } 267 }
241 SerializedString* ss = reinterpret_cast<SerializedString*>(p); 268 SerializedString* ss = reinterpret_cast<SerializedString*>(p);
242 if (PP_VARTYPE_STRING != ss->fixed.type) { 269 if (PP_VARTYPE_STRING != ss->fixed.type &&
270 PP_VARTYPE_ARRAY_BUFFER != ss->fixed.type) {
243 return std::numeric_limits<uint32_t>::max(); 271 return std::numeric_limits<uint32_t>::max();
244 } 272 }
245 uint32_t string_length = ss->fixed.u.string_length; 273 uint32_t string_length = ss->fixed.u.string_length;
246 string_length = RoundedStringBytes(string_length); 274 string_length = RoundedStringBytes(string_length);
247 if (std::numeric_limits<uint32_t>::max() == string_length) { 275 if (std::numeric_limits<uint32_t>::max() == string_length) {
248 return std::numeric_limits<uint32_t>::max(); 276 return std::numeric_limits<uint32_t>::max();
249 } 277 }
250 if (AddWouldOverflow(NACL_OFFSETOF(SerializedString, string_bytes), 278 if (AddWouldOverflow(NACL_OFFSETOF(SerializedString, string_bytes),
251 string_length)) { 279 string_length)) {
252 return std::numeric_limits<uint32_t>::max(); 280 return std::numeric_limits<uint32_t>::max();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 break; 323 break;
296 case PP_VARTYPE_DOUBLE: 324 case PP_VARTYPE_DOUBLE:
297 expected_element_size = sizeof(SerializedDouble); 325 expected_element_size = sizeof(SerializedDouble);
298 break; 326 break;
299 case PP_VARTYPE_STRING: 327 case PP_VARTYPE_STRING:
300 expected_element_size = DeserializeStringSize(p, length); 328 expected_element_size = DeserializeStringSize(p, length);
301 if (std::numeric_limits<uint32_t>::max() == expected_element_size) { 329 if (std::numeric_limits<uint32_t>::max() == expected_element_size) {
302 return std::numeric_limits<uint32_t>::max(); 330 return std::numeric_limits<uint32_t>::max();
303 } 331 }
304 break; 332 break;
333 case PP_VARTYPE_ARRAY_BUFFER:
334 expected_element_size = DeserializeStringSize(p, length);
335 if (std::numeric_limits<uint32_t>::max() == expected_element_size) {
336 return std::numeric_limits<uint32_t>::max();
337 }
338 break;
305 // NB: No default case to trigger -Wswitch-enum, so changes to 339 // NB: No default case to trigger -Wswitch-enum, so changes to
306 // PP_VarType w/o corresponding changes here will cause a 340 // PP_VarType w/o corresponding changes here will cause a
307 // compile-time error. 341 // compile-time error.
308 case PP_VARTYPE_OBJECT: 342 case PP_VARTYPE_OBJECT:
309 case PP_VARTYPE_ARRAY: 343 case PP_VARTYPE_ARRAY:
310 case PP_VARTYPE_DICTIONARY: 344 case PP_VARTYPE_DICTIONARY:
311 case PP_VARTYPE_ARRAY_BUFFER:
312 NACL_NOTREACHED(); 345 NACL_NOTREACHED();
313 break; 346 break;
314 } 347 }
315 if (length < expected_element_size) { 348 if (length < expected_element_size) {
316 return std::numeric_limits<uint32_t>::max(); 349 return std::numeric_limits<uint32_t>::max();
317 } 350 }
318 if (NULL != element_type_ptr) { 351 if (NULL != element_type_ptr) {
319 *element_type_ptr = static_cast<PP_VarType>(sfp->type); 352 *element_type_ptr = static_cast<PP_VarType>(sfp->type);
320 } 353 }
321 return expected_element_size; 354 return expected_element_size;
(...skipping 10 matching lines...) Expand all
332 uint32_t string_length = ss->fixed.u.string_length; 365 uint32_t string_length = ss->fixed.u.string_length;
333 // VarFromUtf8 creates a buffer of size string_length using the browser-side 366 // VarFromUtf8 creates a buffer of size string_length using the browser-side
334 // memory allocation function, and copies string_length bytes from 367 // memory allocation function, and copies string_length bytes from
335 // ss->string_bytes in to that buffer. The ref count of the returned var is 368 // ss->string_bytes in to that buffer. The ref count of the returned var is
336 // 1. 369 // 1.
337 *var = PPBVarInterface()->VarFromUtf8(ss->string_bytes, 370 *var = PPBVarInterface()->VarFromUtf8(ss->string_bytes,
338 string_length); 371 string_length);
339 return true; 372 return true;
340 } 373 }
341 374
375 //
376 // This should be invoked only if DeserializePpVarSize succeeds, i.e.,
377 // there are enough bytes at p.
378 //
379 bool DeserializeArrayBuffer(char* p,
380 PP_Var* var) {
381 SerializedString* ss = reinterpret_cast<SerializedString*>(p);
382 uint32_t buffer_length = ss->fixed.u.string_length;
383 // VarFromUtf8 creates a buffer of size string_length using the browser-side
384 // memory allocation function, and copies string_length bytes from
385 // ss->string_bytes in to that buffer. The ref count of the returned var is
386 // 1.
387 *var = PPBVarArrayBufferInterface()->Create(buffer_length);
388 void* var_buffer = PPBVarArrayBufferInterface()->Map(*var);
389 memcpy(var_buffer, ss->string_bytes, buffer_length);
390 return true;
391 }
392
342 bool DeserializePpVar(char* bytes, 393 bool DeserializePpVar(char* bytes,
343 uint32_t length, 394 uint32_t length,
344 PP_Var* vars, 395 PP_Var* vars,
345 uint32_t argc) { 396 uint32_t argc) {
346 char* p = bytes; 397 char* p = bytes;
347 398
348 for (uint32_t i = 0; i < argc; ++i) { 399 for (uint32_t i = 0; i < argc; ++i) {
349 PP_VarType element_type; 400 PP_VarType element_type;
350 uint32_t element_size = DeserializePpVarSize(p, length, &element_type); 401 uint32_t element_size = DeserializePpVarSize(p, length, &element_type);
351 if (std::numeric_limits<uint32_t>::max() == element_size) { 402 if (std::numeric_limits<uint32_t>::max() == element_size) {
(...skipping 15 matching lines...) Expand all
367 case PP_VARTYPE_DOUBLE: { 418 case PP_VARTYPE_DOUBLE: {
368 SerializedDouble* sd = reinterpret_cast<SerializedDouble*>(p); 419 SerializedDouble* sd = reinterpret_cast<SerializedDouble*>(p);
369 vars[i].value.as_double = sd->double_value; 420 vars[i].value.as_double = sd->double_value;
370 break; 421 break;
371 } 422 }
372 case PP_VARTYPE_STRING: 423 case PP_VARTYPE_STRING:
373 if (!DeserializeString(p, &vars[i])) { 424 if (!DeserializeString(p, &vars[i])) {
374 return false; 425 return false;
375 } 426 }
376 break; 427 break;
428 case PP_VARTYPE_ARRAY_BUFFER:
429 if (!DeserializeArrayBuffer(p, &vars[i])) {
430 return false;
431 }
432 break;
377 case PP_VARTYPE_OBJECT: 433 case PP_VARTYPE_OBJECT:
378 case PP_VARTYPE_ARRAY: 434 case PP_VARTYPE_ARRAY:
379 case PP_VARTYPE_DICTIONARY: 435 case PP_VARTYPE_DICTIONARY:
380 case PP_VARTYPE_ARRAY_BUFFER:
381 NACL_NOTREACHED(); 436 NACL_NOTREACHED();
382 default: 437 default:
383 return false; 438 return false;
384 } 439 }
385 p += element_size; 440 p += element_size;
386 length -= element_size; 441 length -= element_size;
387 } 442 }
388 return true; 443 return true;
389 } 444 }
390 445
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 return false; 514 return false;
460 } 515 }
461 // Read the serialized PP_Vars into the allocated memory. 516 // Read the serialized PP_Vars into the allocated memory.
462 if (!DeserializePpVar(bytes, length, vars, argc)) { 517 if (!DeserializePpVar(bytes, length, vars, argc)) {
463 return false; 518 return false;
464 } 519 }
465 return true; 520 return true;
466 } 521 }
467 522
468 } // namespace ppapi_proxy 523 } // namespace ppapi_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698