OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 define("mojo/public/js/bindings/validator", [ | 5 define("mojo/public/js/bindings/validator", [ |
6 "mojo/public/js/bindings/codec", | 6 "mojo/public/js/bindings/codec", |
7 ], function(codec) { | 7 ], function(codec) { |
yzshen1
2014/08/20 17:04:20
I think the indent is a little unusual.
Maybe the
hansmuller
2014/08/20 17:46:30
Done.
| |
8 | 8 |
9 var validationError = { | 9 var validationError = { |
10 NONE: 'VALIDATION_ERROR_NONE', | 10 NONE: 'VALIDATION_ERROR_NONE', |
11 MISALIGNED_OBJECT: 'VALIDATION_ERROR_MISALIGNED_OBJECT', | 11 MISALIGNED_OBJECT: 'VALIDATION_ERROR_MISALIGNED_OBJECT', |
12 ILLEGAL_MEMORY_RANGE: 'VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE', | 12 ILLEGAL_MEMORY_RANGE: 'VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE', |
13 UNEXPECTED_STRUCT_HEADER: 'VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER', | 13 UNEXPECTED_STRUCT_HEADER: 'VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER', |
14 UNEXPECTED_ARRAY_HEADER: 'VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER', | 14 UNEXPECTED_ARRAY_HEADER: 'VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER', |
15 ILLEGAL_HANDLE: 'VALIDATION_ERROR_ILLEGAL_HANDLE', | 15 ILLEGAL_HANDLE: 'VALIDATION_ERROR_ILLEGAL_HANDLE', |
16 UNEXPECTED_INVALID_HANDLE: 'VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE', | |
16 ILLEGAL_POINTER: 'VALIDATION_ERROR_ILLEGAL_POINTER', | 17 ILLEGAL_POINTER: 'VALIDATION_ERROR_ILLEGAL_POINTER', |
18 UNEXPECTED_NULL_POINTER: 'VALIDATION_ERROR_UNEXPECTED_NULL_POINTER', | |
17 MESSAGE_HEADER_INVALID_FLAG_COMBINATION: | 19 MESSAGE_HEADER_INVALID_FLAG_COMBINATION: |
18 'VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION', | 20 'VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION', |
19 MESSAGE_HEADER_MISSING_REQUEST_ID: | 21 MESSAGE_HEADER_MISSING_REQUEST_ID: |
20 'VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID' | 22 'VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID' |
21 }; | 23 }; |
22 | 24 |
23 var NULL_MOJO_POINTER = "NULL_MOJO_POINTER"; | 25 var NULL_MOJO_POINTER = "NULL_MOJO_POINTER"; |
24 | 26 |
27 function isStringClass(cls) { | |
28 return cls === codec.String || cls === codec.NullableString; | |
29 } | |
30 | |
31 function isHandleClass(cls) { | |
32 return cls === codec.Handle || cls === codec.NullableHandle; | |
33 } | |
34 | |
35 function isNullable(type) { | |
36 return type === codec.NullableString || type === codec.NullableHandle || | |
37 type instanceof codec.NullableArrayOf || | |
yzshen1
2014/08/20 17:04:20
wrong indent. (37 - 39)
hansmuller
2014/08/20 17:46:31
Done.
| |
38 type instanceof codec.NullablePointerTo; | |
39 } | |
40 | |
25 function Validator(message) { | 41 function Validator(message) { |
26 this.message = message; | 42 this.message = message; |
27 this.offset = 0; | 43 this.offset = 0; |
28 this.handleIndex = 0; | 44 this.handleIndex = 0; |
29 } | 45 } |
30 | 46 |
31 Object.defineProperty(Validator.prototype, "offsetLimit", { | 47 Object.defineProperty(Validator.prototype, "offsetLimit", { |
32 get: function() { return this.message.buffer.byteLength; } | 48 get: function() { return this.message.buffer.byteLength; } |
33 }); | 49 }); |
34 | 50 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 return true; | 82 return true; |
67 | 83 |
68 if (index < this.handleIndex || index >= this.handleIndexLimit) | 84 if (index < this.handleIndex || index >= this.handleIndexLimit) |
69 return false; | 85 return false; |
70 | 86 |
71 // This is safe because handle indices are uint32. | 87 // This is safe because handle indices are uint32. |
72 this.handleIndex = index + 1; | 88 this.handleIndex = index + 1; |
73 return true; | 89 return true; |
74 } | 90 } |
75 | 91 |
76 Validator.prototype.validateHandle = function(offset) { | 92 Validator.prototype.validateHandle = function(offset, nullable) { |
yzshen1
2014/08/20 17:04:20
One thing may worth considering:
Passing nullable
hansmuller
2014/08/20 17:46:31
I don't know what the performance impact of an add
yzshen1
2014/08/20 17:54:08
Sounds good.
| |
77 var index = this.message.buffer.getUint32(offset); | 93 var index = this.message.buffer.getUint32(offset); |
94 | |
95 if (index === codec.kEncodedInvalidHandleValue) | |
96 return nullable ? | |
97 validationError.NONE : validationError.UNEXPECTED_INVALID_HANDLE; | |
98 | |
78 if (!this.claimHandle(index)) | 99 if (!this.claimHandle(index)) |
79 return validationError.ILLEGAL_HANDLE; | 100 return validationError.ILLEGAL_HANDLE; |
80 return validationError.NONE; | 101 return validationError.NONE; |
81 } | 102 } |
82 | 103 |
83 Validator.prototype.validateStructHeader = | 104 Validator.prototype.validateStructHeader = |
84 function(offset, minNumBytes, minNumFields) { | 105 function(offset, minNumBytes, minNumFields) { |
85 if (!codec.isAligned(offset)) | 106 if (!codec.isAligned(offset)) |
86 return validationError.MISALIGNED_OBJECT; | 107 return validationError.MISALIGNED_OBJECT; |
87 | 108 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 // NULL_MOJO_POINTER if the pointer represents a null, or JS null if the | 154 // NULL_MOJO_POINTER if the pointer represents a null, or JS null if the |
134 // pointer's value is not valid. | 155 // pointer's value is not valid. |
135 Validator.prototype.decodePointer = function(offset) { | 156 Validator.prototype.decodePointer = function(offset) { |
136 var pointerValue = this.message.buffer.getUint64(offset); | 157 var pointerValue = this.message.buffer.getUint64(offset); |
137 if (pointerValue === 0) | 158 if (pointerValue === 0) |
138 return NULL_MOJO_POINTER; | 159 return NULL_MOJO_POINTER; |
139 var bufferOffset = offset + pointerValue; | 160 var bufferOffset = offset + pointerValue; |
140 return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; | 161 return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; |
141 } | 162 } |
142 | 163 |
143 Validator.prototype.validateArrayPointer = | 164 Validator.prototype.validateArrayPointer = function( |
144 function(offset, elementSize, expectedElementCount, elementType) { | 165 offset, elementSize, expectedElementCount, elementType, nullable) { |
145 var arrayOffset = this.decodePointer(offset); | 166 var arrayOffset = this.decodePointer(offset); |
146 if (arrayOffset === null) | 167 if (arrayOffset === null) |
147 return validationError.ILLEGAL_POINTER; | 168 return validationError.ILLEGAL_POINTER; |
169 | |
148 if (arrayOffset === NULL_MOJO_POINTER) | 170 if (arrayOffset === NULL_MOJO_POINTER) |
149 return validationError.NONE; | 171 return nullable ? |
172 validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; | |
173 | |
150 return this.validateArray( | 174 return this.validateArray( |
151 arrayOffset, elementSize, expectedElementCount, elementType); | 175 arrayOffset, elementSize, expectedElementCount, elementType); |
152 } | 176 } |
153 | 177 |
154 Validator.prototype.validateStructPointer = function(offset, structClass) { | 178 Validator.prototype.validateStructPointer = function( |
179 offset, structClass, nullable) { | |
155 var structOffset = this.decodePointer(offset); | 180 var structOffset = this.decodePointer(offset); |
156 if (structOffset === null) | 181 if (structOffset === null) |
157 return validationError.ILLEGAL_POINTER; | 182 return validationError.ILLEGAL_POINTER; |
183 | |
158 if (structOffset === NULL_MOJO_POINTER) | 184 if (structOffset === NULL_MOJO_POINTER) |
159 return validationError.NONE; | 185 return nullable ? |
186 validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; | |
187 | |
160 return structClass.validate(this, structOffset); | 188 return structClass.validate(this, structOffset); |
161 } | 189 } |
162 | 190 |
163 Validator.prototype.validateStringPointer = function(offset) { | 191 Validator.prototype.validateStringPointer = function(offset) { |
164 return this.validateArrayPointer( | 192 return this.validateArrayPointer( |
165 offset, codec.Uint8.encodedSize, 0, codec.Uint8); | 193 offset, codec.Uint8.encodedSize, 0, codec.Uint8); |
166 } | 194 } |
167 | 195 |
168 // Similar to Array_Data<T>::Validate() | 196 // Similar to Array_Data<T>::Validate() |
169 // mojo/public/cpp/bindings/lib/array_internal.h | 197 // mojo/public/cpp/bindings/lib/array_internal.h |
(...skipping 19 matching lines...) Expand all Loading... | |
189 | 217 |
190 if (expectedElementCount != 0 && numElements != expectedElementCount) | 218 if (expectedElementCount != 0 && numElements != expectedElementCount) |
191 return validationError.UNEXPECTED_ARRAY_HEADER; | 219 return validationError.UNEXPECTED_ARRAY_HEADER; |
192 | 220 |
193 if (!this.claimRange(offset, numBytes)) | 221 if (!this.claimRange(offset, numBytes)) |
194 return validationError.ILLEGAL_MEMORY_RANGE; | 222 return validationError.ILLEGAL_MEMORY_RANGE; |
195 | 223 |
196 // Validate the array's elements if they are pointers or handles. | 224 // Validate the array's elements if they are pointers or handles. |
197 | 225 |
198 var elementsOffset = offset + codec.kArrayHeaderSize; | 226 var elementsOffset = offset + codec.kArrayHeaderSize; |
199 if (elementType === codec.Handle) | 227 var nullable = isNullable(elementType); |
200 return this.validateHandleElements(elementsOffset, numElements); | 228 |
229 if (isHandleClass(elementType)) | |
230 return this.validateHandleElements(elementsOffset, numElements, nullable); | |
231 if (isStringClass(elementType)) | |
232 return this.validateArrayElements( | |
233 elementsOffset, numElements, codec.Uint8, nullable) | |
201 if (elementType instanceof codec.PointerTo) | 234 if (elementType instanceof codec.PointerTo) |
202 return this.validateStructElements( | 235 return this.validateStructElements( |
203 elementsOffset, numElements, elementType.cls); | 236 elementsOffset, numElements, elementType.cls, nullable); |
204 if (elementType instanceof codec.String) | |
205 return this.validateArrayElements( | |
206 elementsOffset, numElements, codec.Uint8); | |
207 if (elementType instanceof codec.ArrayOf) | 237 if (elementType instanceof codec.ArrayOf) |
208 return this.validateArrayElements( | 238 return this.validateArrayElements( |
209 elementsOffset, numElements, elementType.cls); | 239 elementsOffset, numElements, elementType.cls, nullable); |
210 | 240 |
211 return validationError.NONE; | 241 return validationError.NONE; |
212 } | 242 } |
213 | 243 |
214 // Note: the |offset + i * elementSize| computation in the validateFooElements | 244 // Note: the |offset + i * elementSize| computation in the validateFooElements |
215 // methods below is "safe" because elementSize <= 8, offset and | 245 // methods below is "safe" because elementSize <= 8, offset and |
216 // numElements are uint32, and 0 <= i < numElements. | 246 // numElements are uint32, and 0 <= i < numElements. |
217 | 247 |
218 Validator.prototype.validateHandleElements = function(offset, numElements) { | 248 Validator.prototype.validateHandleElements = |
249 function(offset, numElements, nullable) { | |
219 var elementSize = codec.Handle.encodedSize; | 250 var elementSize = codec.Handle.encodedSize; |
220 for (var i = 0; i < numElements; i++) { | 251 for (var i = 0; i < numElements; i++) { |
221 var index = this.message.buffer.getUint32(offset + i * elementSize); | 252 var elementOffset = offset + i * elementSize; |
222 if (!this.claimHandle(index)) | 253 var err = this.validateHandle(elementOffset, nullable); |
223 return validationError.ILLEGAL_HANDLE; | 254 if (err != validationError.NONE) |
255 return err; | |
224 } | 256 } |
225 return validationError.NONE; | 257 return validationError.NONE; |
226 } | 258 } |
227 | 259 |
228 // The elementClass parameter is the element type of the element arrays. | 260 // The elementClass parameter is the element type of the element arrays. |
229 Validator.prototype.validateArrayElements = | 261 Validator.prototype.validateArrayElements = |
230 function(offset, numElements, elementClass) { | 262 function(offset, numElements, elementClass, nullable) { |
231 var elementSize = codec.PointerTo.prototype.encodedSize; | 263 var elementSize = codec.PointerTo.prototype.encodedSize; |
232 for (var i = 0; i < numElements; i++) { | 264 for (var i = 0; i < numElements; i++) { |
233 var elementOffset = offset + i * elementSize; | 265 var elementOffset = offset + i * elementSize; |
234 var err = this.validateArrayPointer( | 266 var err = this.validateArrayPointer( |
235 elementOffset, elementClass.encodedSize, 0, elementClass); | 267 elementOffset, elementClass.encodedSize, 0, elementClass, nullable); |
yzshen1
2014/08/20 17:04:20
wrong indent.
hansmuller
2014/08/20 17:46:31
Done.
| |
236 if (err != validationError.NONE) | 268 if (err != validationError.NONE) |
237 return err; | 269 return err; |
238 } | 270 } |
239 return validationError.NONE; | 271 return validationError.NONE; |
240 } | 272 } |
241 | 273 |
242 Validator.prototype.validateStructElements = | 274 Validator.prototype.validateStructElements = |
243 function(offset, numElements, structClass) { | 275 function(offset, numElements, structClass, nullable) { |
244 var elementSize = codec.PointerTo.prototype.encodedSize; | 276 var elementSize = codec.PointerTo.prototype.encodedSize; |
245 for (var i = 0; i < numElements; i++) { | 277 for (var i = 0; i < numElements; i++) { |
246 var elementOffset = offset + i * elementSize; | 278 var elementOffset = offset + i * elementSize; |
247 var err = this.validateStructPointer(elementOffset, structClass); | 279 var err = |
280 this.validateStructPointer(elementOffset, structClass, nullable); | |
248 if (err != validationError.NONE) | 281 if (err != validationError.NONE) |
249 return err; | 282 return err; |
250 } | 283 } |
251 return validationError.NONE; | 284 return validationError.NONE; |
252 } | 285 } |
253 | 286 |
254 var exports = {}; | 287 var exports = {}; |
255 exports.validationError = validationError; | 288 exports.validationError = validationError; |
256 exports.Validator = Validator; | 289 exports.Validator = Validator; |
257 return exports; | 290 return exports; |
258 }); | 291 }); |
OLD | NEW |