Index: mojo/public/js/bindings/validator.js |
diff --git a/mojo/public/js/bindings/validator.js b/mojo/public/js/bindings/validator.js |
index 837f85a37df59b15758ea8286b91c726c416c998..dad1f59f0dd7e482602529b6473eac9fe5b8d0e2 100644 |
--- a/mojo/public/js/bindings/validator.js |
+++ b/mojo/public/js/bindings/validator.js |
@@ -13,7 +13,9 @@ define("mojo/public/js/bindings/validator", [ |
UNEXPECTED_STRUCT_HEADER: 'VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER', |
UNEXPECTED_ARRAY_HEADER: 'VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER', |
ILLEGAL_HANDLE: 'VALIDATION_ERROR_ILLEGAL_HANDLE', |
+ UNEXPECTED_INVALID_HANDLE: 'VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE', |
ILLEGAL_POINTER: 'VALIDATION_ERROR_ILLEGAL_POINTER', |
+ UNEXPECTED_NULL_POINTER: 'VALIDATION_ERROR_UNEXPECTED_NULL_POINTER', |
MESSAGE_HEADER_INVALID_FLAG_COMBINATION: |
'VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION', |
MESSAGE_HEADER_MISSING_REQUEST_ID: |
@@ -22,6 +24,20 @@ define("mojo/public/js/bindings/validator", [ |
var NULL_MOJO_POINTER = "NULL_MOJO_POINTER"; |
+ function isStringClass(cls) { |
+ return cls === codec.String || cls === codec.NullableString; |
+ } |
+ |
+ function isHandleClass(cls) { |
+ return cls === codec.Handle || cls === codec.NullableHandle; |
+ } |
+ |
+ function isNullable(type) { |
+ return type === codec.NullableString || type === codec.NullableHandle || |
+ type instanceof codec.NullableArrayOf || |
+ type instanceof codec.NullablePointerTo; |
+ } |
+ |
function Validator(message) { |
this.message = message; |
this.offset = 0; |
@@ -73,8 +89,13 @@ define("mojo/public/js/bindings/validator", [ |
return true; |
} |
- Validator.prototype.validateHandle = function(offset) { |
+ Validator.prototype.validateHandle = function(offset, nullable) { |
var index = this.message.buffer.getUint32(offset); |
+ |
+ if (index === codec.kEncodedInvalidHandleValue) |
+ return nullable ? |
+ validationError.NONE : validationError.UNEXPECTED_INVALID_HANDLE; |
+ |
if (!this.claimHandle(index)) |
return validationError.ILLEGAL_HANDLE; |
return validationError.NONE; |
@@ -140,23 +161,30 @@ define("mojo/public/js/bindings/validator", [ |
return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; |
} |
- Validator.prototype.validateArrayPointer = |
- function(offset, elementSize, expectedElementCount, elementType) { |
+ Validator.prototype.validateArrayPointer = function( |
+ offset, elementSize, expectedElementCount, elementType, nullable) { |
var arrayOffset = this.decodePointer(offset); |
if (arrayOffset === null) |
return validationError.ILLEGAL_POINTER; |
+ |
if (arrayOffset === NULL_MOJO_POINTER) |
- return validationError.NONE; |
+ return nullable ? |
+ validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; |
+ |
return this.validateArray( |
arrayOffset, elementSize, expectedElementCount, elementType); |
} |
- Validator.prototype.validateStructPointer = function(offset, structClass) { |
+ Validator.prototype.validateStructPointer = function( |
+ offset, structClass, nullable) { |
var structOffset = this.decodePointer(offset); |
if (structOffset === null) |
return validationError.ILLEGAL_POINTER; |
+ |
if (structOffset === NULL_MOJO_POINTER) |
- return validationError.NONE; |
+ return nullable ? |
+ validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; |
+ |
return structClass.validate(this, structOffset); |
} |
@@ -196,17 +224,19 @@ define("mojo/public/js/bindings/validator", [ |
// Validate the array's elements if they are pointers or handles. |
var elementsOffset = offset + codec.kArrayHeaderSize; |
- if (elementType === codec.Handle) |
- return this.validateHandleElements(elementsOffset, numElements); |
+ var nullable = isNullable(elementType); |
+ |
+ if (isHandleClass(elementType)) |
+ return this.validateHandleElements(elementsOffset, numElements, nullable); |
+ if (isStringClass(elementType)) |
+ return this.validateArrayElements( |
+ elementsOffset, numElements, codec.Uint8, nullable) |
if (elementType instanceof codec.PointerTo) |
return this.validateStructElements( |
- elementsOffset, numElements, elementType.cls); |
- if (elementType instanceof codec.String) |
- return this.validateArrayElements( |
- elementsOffset, numElements, codec.Uint8); |
+ elementsOffset, numElements, elementType.cls, nullable); |
if (elementType instanceof codec.ArrayOf) |
return this.validateArrayElements( |
- elementsOffset, numElements, elementType.cls); |
+ elementsOffset, numElements, elementType.cls, nullable); |
return validationError.NONE; |
} |
@@ -215,24 +245,26 @@ define("mojo/public/js/bindings/validator", [ |
// methods below is "safe" because elementSize <= 8, offset and |
// numElements are uint32, and 0 <= i < numElements. |
- Validator.prototype.validateHandleElements = function(offset, numElements) { |
+ Validator.prototype.validateHandleElements = |
+ function(offset, numElements, nullable) { |
var elementSize = codec.Handle.encodedSize; |
for (var i = 0; i < numElements; i++) { |
- var index = this.message.buffer.getUint32(offset + i * elementSize); |
- if (!this.claimHandle(index)) |
- return validationError.ILLEGAL_HANDLE; |
+ var elementOffset = offset + i * elementSize; |
+ var err = this.validateHandle(elementOffset, nullable); |
+ if (err != validationError.NONE) |
+ return err; |
} |
return validationError.NONE; |
} |
// The elementClass parameter is the element type of the element arrays. |
Validator.prototype.validateArrayElements = |
- function(offset, numElements, elementClass) { |
+ function(offset, numElements, elementClass, nullable) { |
var elementSize = codec.PointerTo.prototype.encodedSize; |
for (var i = 0; i < numElements; i++) { |
var elementOffset = offset + i * elementSize; |
var err = this.validateArrayPointer( |
- elementOffset, elementClass.encodedSize, 0, elementClass); |
+ elementOffset, elementClass.encodedSize, 0, elementClass, nullable); |
if (err != validationError.NONE) |
return err; |
} |
@@ -240,11 +272,12 @@ define("mojo/public/js/bindings/validator", [ |
} |
Validator.prototype.validateStructElements = |
- function(offset, numElements, structClass) { |
+ function(offset, numElements, structClass, nullable) { |
var elementSize = codec.PointerTo.prototype.encodedSize; |
for (var i = 0; i < numElements; i++) { |
var elementOffset = offset + i * elementSize; |
- var err = this.validateStructPointer(elementOffset, structClass); |
+ var err = |
+ this.validateStructPointer(elementOffset, structClass, nullable); |
if (err != validationError.NONE) |
return err; |
} |