| Index: third_party/mojo/src/mojo/public/dart/src/codec.dart
|
| diff --git a/third_party/mojo/src/mojo/public/dart/src/codec.dart b/third_party/mojo/src/mojo/public/dart/src/codec.dart
|
| index 7ad8370bca4adc8ba0c6f2290d2fda5ea3f2068d..268daee2a61fcec7b7f9e0686484c68057ef35b4 100644
|
| --- a/third_party/mojo/src/mojo/public/dart/src/codec.dart
|
| +++ b/third_party/mojo/src/mojo/public/dart/src/codec.dart
|
| @@ -18,6 +18,12 @@ const int kElementNullable = (1 << 1);
|
| bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
|
| bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
|
|
|
| +class MojoCodecError {
|
| + final String message;
|
| + MojoCodecError(this.message);
|
| + String toString() => message;
|
| +}
|
| +
|
| class _EncoderBuffer {
|
| ByteData buffer;
|
| List<core.MojoHandle> handles;
|
| @@ -88,7 +94,7 @@ class Encoder {
|
|
|
| void encodeUint8(int value, int offset) {
|
| if (value < 0) {
|
| - throw '$kErrorUnsigned: $val';
|
| + throw new MojoCodecError('$kErrorUnsigned: $val');
|
| }
|
| _buffer.buffer.setUint8(_base + offset, value);
|
| }
|
| @@ -98,7 +104,7 @@ class Encoder {
|
|
|
| void encodeUint16(int value, int offset) {
|
| if (value < 0) {
|
| - throw '$kErrorUnsigned: $val';
|
| + throw new MojoCodecError('$kErrorUnsigned: $val');
|
| }
|
| _buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN);
|
| }
|
| @@ -108,7 +114,7 @@ class Encoder {
|
|
|
| void encodeUint32(int value, int offset) {
|
| if (value < 0) {
|
| - throw '$kErrorUnsigned: $val';
|
| + throw new MojoCodecError('$kErrorUnsigned: $val');
|
| }
|
| _buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN);
|
| }
|
| @@ -118,7 +124,7 @@ class Encoder {
|
|
|
| void encodeUint64(int value, int offset) {
|
| if (value < 0) {
|
| - throw '$kErrorUnsigned: $val';
|
| + throw new MojoCodecError('$kErrorUnsigned: $val');
|
| }
|
| _buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN);
|
| }
|
| @@ -176,14 +182,16 @@ class Encoder {
|
|
|
| void encodeNullPointer(int offset, bool nullable) {
|
| if (!nullable) {
|
| - throw 'Trying to encode a null pointer for a non-nullable type';
|
| + throw new MojoCodecError(
|
| + 'Trying to encode a null pointer for a non-nullable type');
|
| }
|
| _buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN);
|
| }
|
|
|
| void encodeInvalideHandle(int offset, bool nullable) {
|
| if (!nullable) {
|
| - throw 'Trying to encode a null pointer for a non-nullable type';
|
| + throw new MojoCodecError(
|
| + 'Trying to encode a null pointer for a non-nullable type');
|
| }
|
| _buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN);
|
| }
|
| @@ -207,7 +215,8 @@ class Encoder {
|
| int elementSize, int length, int offset, int expectedLength) {
|
| if ((expectedLength != kUnspecifiedArrayLength) &&
|
| (expectedLength != length)) {
|
| - throw 'Trying to encode a fixed array of incorrect length';
|
| + throw new MojoCodecError(
|
| + 'Trying to encode a fixed array of incorrect length');
|
| }
|
| return encoderForArrayByTotalSize(length * elementSize, length, offset);
|
| }
|
| @@ -226,7 +235,8 @@ class Encoder {
|
| }
|
| if ((expectedLength != kUnspecifiedArrayLength) &&
|
| (expectedLength != value.length)) {
|
| - throw 'Trying to encode a fixed array of incorrect size.';
|
| + throw new MojoCodecError(
|
| + 'Trying to encode a fixed array of incorrect size.');
|
| }
|
| var bytes = new Uint8List((value.length + 7) ~/ kAlignment);
|
| for (int i = 0; i < bytes.length; ++i) {
|
| @@ -411,34 +421,34 @@ class Encoder {
|
| }
|
|
|
| void appendInt8Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Int8List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Int8List.fromList(value).buffer));
|
|
|
| void appendUint8Array(List<int> value) =>
|
| appendBytes(new Uint8List.fromList(value));
|
|
|
| void appendInt16Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Int16List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Int16List.fromList(value).buffer));
|
|
|
| void appendUint16Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Uint16List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Uint16List.fromList(value).buffer));
|
|
|
| void appendInt32Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Int32List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Int32List.fromList(value).buffer));
|
|
|
| void appendUint32Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Uint32List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Uint32List.fromList(value).buffer));
|
|
|
| void appendInt64Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Int64List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Int64List.fromList(value).buffer));
|
|
|
| void appendUint64Array(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Uint64List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Uint64List.fromList(value).buffer));
|
|
|
| void appendFloatArray(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Float32List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Float32List.fromList(value).buffer));
|
|
|
| void appendDoubleArray(List<int> value) =>
|
| - appendBytes(new Uint8List.view(new Float64List.fromList(value)));
|
| + appendBytes(new Uint8List.view(new Float64List.fromList(value).buffer));
|
|
|
| Encoder encoderForMap(int offset) {
|
| encodePointerToNextUnclaimed(offset);
|
| @@ -447,16 +457,59 @@ class Encoder {
|
| }
|
|
|
|
|
| +class _Validator {
|
| + final int _maxMemory;
|
| + final int _numberOfHandles;
|
| + int _minNextClaimedHandle = 0;
|
| + int _minNextMemory = 0;
|
| +
|
| + _Validator(this._maxMemory, this._numberOfHandles);
|
| +
|
| + void claimHandle(int handle) {
|
| + if (handle < _minNextClaimedHandle) {
|
| + throw new MojoCodecError('Trying to access handle out of order.');
|
| + }
|
| + if (handle >= _numberOfHandles) {
|
| + throw new MojoCodecError('Trying to access non present handle.');
|
| + }
|
| + _minNextClaimedHandle = handle + 1;
|
| + }
|
| +
|
| + void claimMemory(int start, int end) {
|
| + if ((start % kAlignment) != 0) {
|
| + throw new MojoCodecError('Incorrect starting alignment: $start.');
|
| + }
|
| + if (start < _minNextMemory) {
|
| + throw new MojoCodecError('Trying to access memory out of order.');
|
| + }
|
| + if (end < start) {
|
| + throw new MojoCodecError('Incorrect memory range.');
|
| + }
|
| + if (end > _maxMemory) {
|
| + throw new MojoCodecError('Trying to access out of range memory.');
|
| + }
|
| + _minNextMemory = align(end);
|
| + }
|
| +}
|
| +
|
| +
|
| class Decoder {
|
| + _Validator _validator;
|
| Message _message;
|
| int _base = 0;
|
|
|
| - Decoder(this._message, [this._base = 0]);
|
| + Decoder(this._message, [this._base = 0, this._validator = null]) {
|
| + if (_validator == null) {
|
| + _validator = new _Validator(
|
| + _message.buffer.lengthInBytes, _message.handles.length);
|
| + }
|
| + }
|
|
|
| - Decoder getDecoderAtPosition(int offset) => new Decoder(_message, offset);
|
| + Decoder getDecoderAtPosition(int offset) =>
|
| + new Decoder(_message, offset, _validator);
|
|
|
| - factory Decoder.atOffset(Decoder d, int offset) =>
|
| - new Decoder(d._message, offset);
|
| + factory Decoder.atOffset(Decoder d, int offset, _Validator validator) =>
|
| + new Decoder(d._message, offset, validator);
|
|
|
| ByteData get _buffer => _message.buffer;
|
| List<core.MojoHandle> get _handles => _message.handles;
|
| @@ -487,10 +540,12 @@ class Decoder {
|
| int index = decodeInt32(offset);
|
| if (index == -1) {
|
| if (!nullable) {
|
| - throw 'Trying to decode an invalid handle from a non-nullable type.';
|
| + throw new MojoCodecError(
|
| + 'Trying to decode an invalid handle from a non-nullable type.');
|
| }
|
| return new core.MojoHandle(core.MojoHandle.INVALID);
|
| }
|
| + _validator.claimHandle(index);
|
| return _handles[index];
|
| }
|
|
|
| @@ -524,17 +579,26 @@ class Decoder {
|
| int pointerOffset = decodeUint64(offset);
|
| if (pointerOffset == 0) {
|
| if (!nullable) {
|
| - throw 'Trying to decode a null pointer for a non-nullable type';
|
| + throw new MojoCodecError(
|
| + 'Trying to decode a null pointer for a non-nullable type');
|
| }
|
| return null;
|
| }
|
| int newPosition = (basePosition + pointerOffset);
|
| - return new Decoder.atOffset(this, newPosition);
|
| + return new Decoder.atOffset(this, newPosition, _validator);
|
| }
|
|
|
| DataHeader decodeDataHeader() {
|
| + _validator.claimMemory(_base, _base + DataHeader.kHeaderSize);
|
| int size = decodeUint32(DataHeader.kSizeOffset);
|
| int numFields = decodeUint32(DataHeader.kNumFieldsOffset);
|
| + if (size < 0) {
|
| + throw new MojoCodecError('Negative size.');
|
| + }
|
| + if (numFields < 0) {
|
| + throw new MojoCodecError('Negative number of fields.');
|
| + }
|
| + _validator.claimMemory(_base + DataHeader.kHeaderSize, _base + size);
|
| return new DataHeader(size, numFields);
|
| }
|
|
|
| @@ -542,11 +606,13 @@ class Decoder {
|
| DataHeader decodeDataHeaderForBoolArray(int expectedLength) {
|
| var header = decodeDataHeader();
|
| if (header.size < DataHeader.kHeaderSize + (header.numFields + 7) ~/ 8) {
|
| - throw 'Array header is incorrect';
|
| + throw new MojoCodecError('Array header is incorrect');
|
| }
|
| if ((expectedLength != kUnspecifiedArrayLength) &&
|
| (header.numFields != expectedLength)) {
|
| - throw 'Incorrect array length';
|
| + throw new MojoCodecError(
|
| + 'Incorrect array length. Expected $expectedLength, but got '
|
| + '${header.numFields}.');
|
| }
|
| return header;
|
| }
|
| @@ -576,11 +642,14 @@ class Decoder {
|
| DataHeader decodeDataHeaderForArray(int elementSize, int expectedLength) {
|
| var header = decodeDataHeader();
|
| if (header.size < DataHeader.kHeaderSize + header.numFields * elementSize) {
|
| - throw 'Array header is incorrect: $header, elementSize = $elementSize';
|
| + throw new MojoCodecError(
|
| + 'Array header is incorrect: $header, elementSize = $elementSize');
|
| }
|
| if ((expectedLength != kUnspecifiedArrayLength) &&
|
| (header.numFields != expectedLength)) {
|
| - throw 'Incorrect array length.';
|
| + throw new MojoCodecError(
|
| + 'Incorrect array length. Expected $expectedLength, but got '
|
| + '${header.numFields}');
|
| }
|
| return header;
|
| }
|
| @@ -588,11 +657,11 @@ class Decoder {
|
| DataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
|
| decodeDataHeaderForArray(kPointerSize, expectedLength);
|
|
|
| - List<int> decodeArray(Function arrayViewer,
|
| - int elementSize,
|
| - int offset,
|
| - int nullability,
|
| - int expectedLength) {
|
| + List decodeArray(Function arrayViewer,
|
| + int elementSize,
|
| + int offset,
|
| + int nullability,
|
| + int expectedLength) {
|
| Decoder d = decodePointer(offset, isArrayNullable(nullability));
|
| if (d == null) {
|
| return null;
|
| @@ -728,4 +797,17 @@ class Decoder {
|
| }
|
| return _stringOfUtf8(bytes);
|
| }
|
| +
|
| + DataHeader decodeDataHeaderForMap() {
|
| + var header = decodeDataHeader();
|
| + if (header.size != kMapStructHeader.size) {
|
| + throw new MojoCodecError(
|
| + 'Incorrect header for map. The size is incorrect.');
|
| + }
|
| + if (header.numFields != kMapStructHeader.numFields) {
|
| + throw new MojoCodecError(
|
| + 'Incorrect header for map. The number of fields is incorrect.');
|
| + }
|
| + return header;
|
| + }
|
| }
|
|
|