diff options
Diffstat (limited to 'mojo/public/js/validator.js')
-rw-r--r-- | mojo/public/js/validator.js | 356 |
1 files changed, 0 insertions, 356 deletions
diff --git a/mojo/public/js/validator.js b/mojo/public/js/validator.js deleted file mode 100644 index a6be692..0000000 --- a/mojo/public/js/validator.js +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -define("mojo/public/js/validator", [ - "mojo/public/js/codec", -], function(codec) { - - var validationError = { - NONE: 'VALIDATION_ERROR_NONE', - MISALIGNED_OBJECT: 'VALIDATION_ERROR_MISALIGNED_OBJECT', - ILLEGAL_MEMORY_RANGE: 'VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE', - 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: - 'VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID', - DIFFERENT_SIZED_ARRAYS_IN_MAP: - 'VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP', - }; - - 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; - this.handleIndex = 0; - } - - Object.defineProperty(Validator.prototype, "offsetLimit", { - get: function() { return this.message.buffer.byteLength; } - }); - - Object.defineProperty(Validator.prototype, "handleIndexLimit", { - get: function() { return this.message.handles.length; } - }); - - // True if we can safely allocate a block of bytes from start to - // to start + numBytes. - Validator.prototype.isValidRange = function(start, numBytes) { - // Only positive JavaScript integers that are less than 2^53 - // (Number.MAX_SAFE_INTEGER) can be represented exactly. - if (start < this.offset || numBytes <= 0 || - !Number.isSafeInteger(start) || - !Number.isSafeInteger(numBytes)) - return false; - - var newOffset = start + numBytes; - if (!Number.isSafeInteger(newOffset) || newOffset > this.offsetLimit) - return false; - - return true; - } - - Validator.prototype.claimRange = function(start, numBytes) { - if (this.isValidRange(start, numBytes)) { - this.offset = start + numBytes; - return true; - } - return false; - } - - Validator.prototype.claimHandle = function(index) { - if (index === codec.kEncodedInvalidHandleValue) - return true; - - if (index < this.handleIndex || index >= this.handleIndexLimit) - return false; - - // This is safe because handle indices are uint32. - this.handleIndex = index + 1; - return true; - } - - 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; - } - - Validator.prototype.validateStructHeader = - function(offset, minNumBytes, minNumFields) { - if (!codec.isAligned(offset)) - return validationError.MISALIGNED_OBJECT; - - if (!this.isValidRange(offset, codec.kStructHeaderSize)) - return validationError.ILLEGAL_MEMORY_RANGE; - - var numBytes = this.message.buffer.getUint32(offset); - var numFields = this.message.buffer.getUint32(offset + 4); - - if (numBytes < minNumBytes || numFields < minNumFields) - return validationError.UNEXPECTED_STRUCT_HEADER; - - if (!this.claimRange(offset, numBytes)) - return validationError.ILLEGAL_MEMORY_RANGE; - - return validationError.NONE; - } - - Validator.prototype.validateMessageHeader = function() { - var err = this.validateStructHeader(0, codec.kMessageHeaderSize, 2); - if (err != validationError.NONE) - return err; - - var numBytes = this.message.getHeaderNumBytes(); - var numFields = this.message.getHeaderNumFields(); - - var validNumFieldsAndNumBytes = - (numFields == 2 && numBytes == codec.kMessageHeaderSize) || - (numFields == 3 && - numBytes == codec.kMessageWithRequestIDHeaderSize) || - (numFields > 3 && - numBytes >= codec.kMessageWithRequestIDHeaderSize); - if (!validNumFieldsAndNumBytes) - return validationError.UNEXPECTED_STRUCT_HEADER; - - var expectsResponse = this.message.expectsResponse(); - var isResponse = this.message.isResponse(); - - if (numFields == 2 && (expectsResponse || isResponse)) - return validationError.MESSAGE_HEADER_MISSING_REQUEST_ID; - - if (isResponse && expectsResponse) - return validationError.MESSAGE_HEADER_INVALID_FLAG_COMBINATION; - - return validationError.NONE; - } - - // Returns the message.buffer relative offset this pointer "points to", - // NULL_MOJO_POINTER if the pointer represents a null, or JS null if the - // pointer's value is not valid. - Validator.prototype.decodePointer = function(offset) { - var pointerValue = this.message.buffer.getUint64(offset); - if (pointerValue === 0) - return NULL_MOJO_POINTER; - var bufferOffset = offset + pointerValue; - return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; - } - - Validator.prototype.validateArrayPointer = function( - offset, elementSize, elementType, nullable, expectedDimensionSizes, - currentDimension) { - var arrayOffset = this.decodePointer(offset); - if (arrayOffset === null) - return validationError.ILLEGAL_POINTER; - - if (arrayOffset === NULL_MOJO_POINTER) - return nullable ? - validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; - - return this.validateArray(arrayOffset, elementSize, elementType, - expectedDimensionSizes, currentDimension); - } - - 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 nullable ? - validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; - - return structClass.validate(this, structOffset); - } - - // This method assumes that the array at arrayPointerOffset has - // been validated. - - Validator.prototype.arrayLength = function(arrayPointerOffset) { - var arrayOffset = this.decodePointer(arrayPointerOffset); - return this.message.buffer.getUint32(arrayOffset + 4); - } - - Validator.prototype.validateMapPointer = function( - offset, mapIsNullable, keyClass, valueClass, valueIsNullable) { - // Validate the implicit map struct: - // struct {array<keyClass> keys; array<valueClass> values}; - var structOffset = this.decodePointer(offset); - if (structOffset === null) - return validationError.ILLEGAL_POINTER; - - if (structOffset === NULL_MOJO_POINTER) - return mapIsNullable ? - validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; - - var mapEncodedSize = codec.kStructHeaderSize + codec.kMapStructPayloadSize; - var err = this.validateStructHeader(structOffset, mapEncodedSize, 2); - if (err !== validationError.NONE) - return err; - - // Validate the keys array. - var keysArrayPointerOffset = structOffset + codec.kStructHeaderSize; - err = this.validateArrayPointer( - keysArrayPointerOffset, keyClass.encodedSize, keyClass, false, [0], 0); - if (err !== validationError.NONE) - return err; - - // Validate the values array. - var valuesArrayPointerOffset = keysArrayPointerOffset + 8; - var valuesArrayDimensions = [0]; // Validate the actual length below. - if (valueClass instanceof codec.ArrayOf) - valuesArrayDimensions = - valuesArrayDimensions.concat(valueClass.dimensions()); - var err = this.validateArrayPointer(valuesArrayPointerOffset, - valueClass.encodedSize, - valueClass, - valueIsNullable, - valuesArrayDimensions, - 0); - if (err !== validationError.NONE) - return err; - - // Validate the lengths of the keys and values arrays. - var keysArrayLength = this.arrayLength(keysArrayPointerOffset); - var valuesArrayLength = this.arrayLength(valuesArrayPointerOffset); - if (keysArrayLength != valuesArrayLength) - return validationError.DIFFERENT_SIZED_ARRAYS_IN_MAP; - - return validationError.NONE; - } - - Validator.prototype.validateStringPointer = function(offset, nullable) { - return this.validateArrayPointer( - offset, codec.Uint8.encodedSize, codec.Uint8, nullable, [0], 0); - } - - // Similar to Array_Data<T>::Validate() - // mojo/public/cpp/bindings/lib/array_internal.h - - Validator.prototype.validateArray = - function (offset, elementSize, elementType, expectedDimensionSizes, - currentDimension) { - if (!codec.isAligned(offset)) - return validationError.MISALIGNED_OBJECT; - - if (!this.isValidRange(offset, codec.kArrayHeaderSize)) - return validationError.ILLEGAL_MEMORY_RANGE; - - var numBytes = this.message.buffer.getUint32(offset); - var numElements = this.message.buffer.getUint32(offset + 4); - - // Note: this computation is "safe" because elementSize <= 8 and - // numElements is a uint32. - var elementsTotalSize = (elementType === codec.PackedBool) ? - Math.ceil(numElements / 8) : (elementSize * numElements); - - if (numBytes < codec.kArrayHeaderSize + elementsTotalSize) - return validationError.UNEXPECTED_ARRAY_HEADER; - - if (expectedDimensionSizes[currentDimension] != 0 && - numElements != expectedDimensionSizes[currentDimension]) { - return validationError.UNEXPECTED_ARRAY_HEADER; - } - - if (!this.claimRange(offset, numBytes)) - return validationError.ILLEGAL_MEMORY_RANGE; - - // Validate the array's elements if they are pointers or handles. - - var elementsOffset = offset + codec.kArrayHeaderSize; - var nullable = isNullable(elementType); - - if (isHandleClass(elementType)) - return this.validateHandleElements(elementsOffset, numElements, nullable); - if (isStringClass(elementType)) - return this.validateArrayElements( - elementsOffset, numElements, codec.Uint8, nullable, [0], 0); - if (elementType instanceof codec.PointerTo) - return this.validateStructElements( - elementsOffset, numElements, elementType.cls, nullable); - if (elementType instanceof codec.ArrayOf) - return this.validateArrayElements( - elementsOffset, numElements, elementType.cls, nullable, - expectedDimensionSizes, currentDimension + 1); - - return validationError.NONE; - } - - // Note: the |offset + i * elementSize| computation in the validateFooElements - // methods below is "safe" because elementSize <= 8, offset and - // numElements are uint32, and 0 <= i < numElements. - - Validator.prototype.validateHandleElements = - function(offset, numElements, nullable) { - var elementSize = codec.Handle.encodedSize; - for (var i = 0; i < numElements; i++) { - 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, nullable, - expectedDimensionSizes, currentDimension) { - 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, elementClass, nullable, - expectedDimensionSizes, currentDimension); - if (err != validationError.NONE) - return err; - } - return validationError.NONE; - } - - Validator.prototype.validateStructElements = - 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, nullable); - if (err != validationError.NONE) - return err; - } - return validationError.NONE; - } - - var exports = {}; - exports.validationError = validationError; - exports.Validator = Validator; - return exports; -}); |