Index: mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java |
diff --git a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java |
index 740e64b507b122018a3004e8bdbaed6b4d78569c..efb984264e7f9b5e910cb11f5a457187f0fe6f56 100644 |
--- a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java |
+++ b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java |
@@ -121,6 +121,15 @@ public class Decoder { |
mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE); |
int size = readInt(DataHeader.SIZE_OFFSET); |
int numFields = readInt(DataHeader.NUM_FIELDS_OFFSET); |
+ if (size < 0) { |
+ throw new DeserializationException( |
+ "Negative size. Unsigned integers are not valid for java."); |
+ } |
+ if (numFields < 0) { |
+ throw new DeserializationException( |
+ "Negative number of fields. Unsigned integers are not valid for java."); |
+ } |
+ |
// Claim the remaining memory. |
mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + size); |
DataHeader res = new DataHeader(size, numFields); |
@@ -128,24 +137,18 @@ public class Decoder { |
} |
/** |
- * Deserializes a {@link DataHeader} of an array at the given offset. |
- * |
- * @param expectedLength the expected length of the array. |
+ * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an |
+ * array where element have the given size. |
*/ |
- public DataHeader readArrayDataHeader(int expectedLength) { |
- DataHeader dataHeader = readDataHeader(); |
- if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH |
- && dataHeader.numFields != expectedLength) { |
- throw new DeserializationException("Incorrect array length. Expected: " + |
- expectedLength + ", but got: " + dataHeader.numFields + "."); |
- } |
- return dataHeader; |
+ public DataHeader readDataHeaderForPointerArray(int expectedLength) { |
+ return readDataHeaderForArray(8, expectedLength); |
} |
/** |
* Deserializes a byte at the given offset. |
*/ |
public byte readByte(int offset) { |
+ validateBufferSize(offset, 1); |
return mMessage.getData().get(mBaseOffset + offset); |
} |
@@ -153,6 +156,7 @@ public class Decoder { |
* Deserializes a boolean at the given offset, re-using any partially read byte. |
*/ |
public boolean readBoolean(int offset, int bit) { |
+ validateBufferSize(offset, 1); |
return (readByte(offset) & (1 << bit)) != 0; |
} |
@@ -160,6 +164,7 @@ public class Decoder { |
* Deserializes a short at the given offset. |
*/ |
public short readShort(int offset) { |
+ validateBufferSize(offset, 2); |
return mMessage.getData().getShort(mBaseOffset + offset); |
} |
@@ -167,6 +172,7 @@ public class Decoder { |
* Deserializes an int at the given offset. |
*/ |
public int readInt(int offset) { |
+ validateBufferSize(offset, 4); |
return mMessage.getData().getInt(mBaseOffset + offset); |
} |
@@ -174,6 +180,7 @@ public class Decoder { |
* Deserializes a float at the given offset. |
*/ |
public float readFloat(int offset) { |
+ validateBufferSize(offset, 4); |
return mMessage.getData().getFloat(mBaseOffset + offset); |
} |
@@ -181,6 +188,7 @@ public class Decoder { |
* Deserializes a long at the given offset. |
*/ |
public long readLong(int offset) { |
+ validateBufferSize(offset, 8); |
return mMessage.getData().getLong(mBaseOffset + offset); |
} |
@@ -188,6 +196,7 @@ public class Decoder { |
* Deserializes a double at the given offset. |
*/ |
public double readDouble(int offset) { |
+ validateBufferSize(offset, 8); |
return mMessage.getData().getDouble(mBaseOffset + offset); |
} |
@@ -219,8 +228,8 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
- byte[] bytes = new byte[si.numFields + 7 / BindingsHelper.ALIGNMENT]; |
+ DataHeader si = d.readDataHeaderForBooleanArray(expectedLength); |
+ byte[] bytes = new byte[(si.numFields + 7) / BindingsHelper.ALIGNMENT]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().get(bytes); |
boolean[] result = new boolean[si.numFields]; |
@@ -243,7 +252,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(1, expectedLength); |
byte[] result = new byte[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().get(result); |
@@ -258,7 +267,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(2, expectedLength); |
short[] result = new short[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().asShortBuffer().get(result); |
@@ -273,7 +282,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
int[] result = new int[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().asIntBuffer().get(result); |
@@ -288,7 +297,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
float[] result = new float[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().asFloatBuffer().get(result); |
@@ -303,7 +312,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(8, expectedLength); |
long[] result = new long[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().asLongBuffer().get(result); |
@@ -318,7 +327,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(8, expectedLength); |
double[] result = new double[si.numFields]; |
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); |
d.mMessage.getData().asDoubleBuffer().get(result); |
@@ -422,7 +431,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
Handle[] result = new Handle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readHandle( |
@@ -441,7 +450,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
UntypedHandle[] result = new UntypedHandle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readUntypedHandle( |
@@ -460,7 +469,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readConsumerHandle( |
@@ -479,7 +488,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readProducerHandle( |
@@ -499,7 +508,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
MessagePipeHandle[] result = new MessagePipeHandle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readMessagePipeHandle( |
@@ -519,7 +528,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
SharedBufferHandle[] result = new SharedBufferHandle[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
result[i] = d.readSharedBufferHandle( |
@@ -539,7 +548,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
S[] result = manager.buildArray(si.numFields); |
for (int i = 0; i < result.length; ++i) { |
// This cast is necessary because java 6 doesn't handle wildcard correctly when using |
@@ -562,7 +571,7 @@ public class Decoder { |
if (d == null) { |
return null; |
} |
- DataHeader si = d.readArrayDataHeader(expectedLength); |
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength); |
@SuppressWarnings("unchecked") |
InterfaceRequest<I>[] result = new InterfaceRequest[si.numFields]; |
for (int i = 0; i < result.length; ++i) { |
@@ -579,4 +588,43 @@ public class Decoder { |
private Decoder getDecoderAtPosition(int offset) { |
return new Decoder(mMessage, mValidator, offset); |
} |
+ |
+ /** |
+ * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an |
+ * array of booleans. |
+ */ |
+ private DataHeader readDataHeaderForBooleanArray(int expectedLength) { |
+ DataHeader dataHeader = readDataHeader(); |
+ if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.numFields + 7) / 8) { |
+ throw new DeserializationException("Array header is incorrect."); |
+ } |
+ if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH |
+ && dataHeader.numFields != expectedLength) { |
+ throw new DeserializationException("Incorrect array length. Expected: " + |
+ expectedLength + ", but got: " + dataHeader.numFields + "."); |
+ } |
+ return dataHeader; |
+ } |
+ |
+ /** |
+ * Deserializes a {@link DataHeader} of an array at the given offset. |
+ */ |
+ private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) { |
+ DataHeader dataHeader = readDataHeader(); |
+ if (dataHeader.size < (DataHeader.HEADER_SIZE + elementSize * dataHeader.numFields)) { |
+ throw new DeserializationException("Array header is incorrect."); |
+ } |
+ if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH |
+ && dataHeader.numFields != expectedLength) { |
+ throw new DeserializationException("Incorrect array length. Expected: " + |
+ expectedLength + ", but got: " + dataHeader.numFields + "."); |
+ } |
+ return dataHeader; |
+ } |
+ |
+ private void validateBufferSize(int offset, int size) { |
+ if (mMessage.getData().limit() < offset + size) { |
+ throw new DeserializationException("Buffer is smaller than expected."); |
+ } |
+ } |
} |