Commit 1e342dff authored by qsr's avatar qsr Committed by Commit bot

mojo: Validate fixed size array for the mojo java bindings.

R=ppi@chromium.org

Review URL: https://codereview.chromium.org/522653004

Cr-Commit-Position: refs/heads/master@{#292862}
parent f0a439da
...@@ -44,6 +44,7 @@ android_library("bindings") { ...@@ -44,6 +44,7 @@ android_library("bindings") {
"bindings/src/org/chromium/mojo/bindings/MessageWithHeader.java", "bindings/src/org/chromium/mojo/bindings/MessageWithHeader.java",
"bindings/src/org/chromium/mojo/bindings/RouterImpl.java", "bindings/src/org/chromium/mojo/bindings/RouterImpl.java",
"bindings/src/org/chromium/mojo/bindings/Router.java", "bindings/src/org/chromium/mojo/bindings/Router.java",
"bindings/src/org/chromium/mojo/bindings/SerializationException.java",
"bindings/src/org/chromium/mojo/bindings/SideEffectFreeCloseable.java", "bindings/src/org/chromium/mojo/bindings/SideEffectFreeCloseable.java",
"bindings/src/org/chromium/mojo/bindings/Struct.java", "bindings/src/org/chromium/mojo/bindings/Struct.java",
] ]
......
...@@ -28,6 +28,11 @@ public class BindingsHelper { ...@@ -28,6 +28,11 @@ public class BindingsHelper {
*/ */
public static final int POINTER_SIZE = 8; public static final int POINTER_SIZE = 8;
/**
* The value used for the expected length of a non-fixed size array.
*/
public static final int UNSPECIFIED_ARRAY_LENGTH = -1;
/** /**
* Align |size| on {@link BindingsHelper#ALIGNMENT}. * Align |size| on {@link BindingsHelper#ALIGNMENT}.
*/ */
......
...@@ -226,7 +226,8 @@ public class Encoder { ...@@ -226,7 +226,8 @@ public class Encoder {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encode(v.getBytes(Charset.forName("utf8")), offset); encode(v.getBytes(
Charset.forName("utf8")), offset, BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
} }
/** /**
...@@ -286,18 +287,22 @@ public class Encoder { ...@@ -286,18 +287,22 @@ public class Encoder {
/** /**
* Returns an {@link Encoder} suitable for encoding an array of pointer of the given length. * Returns an {@link Encoder} suitable for encoding an array of pointer of the given length.
*/ */
public Encoder encodePointerArray(int length, int offset) { public Encoder encodePointerArray(int length, int offset, int expectedLength) {
return encoderForArray(BindingsHelper.POINTER_SIZE, length, offset); return encoderForArray(BindingsHelper.POINTER_SIZE, length, offset, expectedLength);
} }
/** /**
* Encodes an array of booleans. * Encodes an array of booleans.
*/ */
public void encode(boolean[] v, int offset) { public void encode(boolean[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH &&
expectedLength != v.length) {
throw new SerializationException("Trying to encode a fixed array of incorrect length.");
}
byte[] bytes = new byte[(v.length + 7) / BindingsHelper.ALIGNMENT]; byte[] bytes = new byte[(v.length + 7) / BindingsHelper.ALIGNMENT];
for (int i = 0; i < bytes.length; ++i) { for (int i = 0; i < bytes.length; ++i) {
for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) { for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
...@@ -313,78 +318,83 @@ public class Encoder { ...@@ -313,78 +318,83 @@ public class Encoder {
/** /**
* Encodes an array of bytes. * Encodes an array of bytes.
*/ */
public void encode(byte[] v, int offset) { public void encode(byte[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH &&
expectedLength != v.length) {
throw new SerializationException("Trying to encode a fixed array of incorrect length.");
}
encodeByteArray(v, v.length, offset); encodeByteArray(v, v.length, offset);
} }
/** /**
* Encodes an array of shorts. * Encodes an array of shorts.
*/ */
public void encode(short[] v, int offset) { public void encode(short[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encoderForArray(2, v.length, offset).append(v); encoderForArray(2, v.length, offset, expectedLength).append(v);
} }
/** /**
* Encodes an array of ints. * Encodes an array of ints.
*/ */
public void encode(int[] v, int offset) { public void encode(int[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encoderForArray(4, v.length, offset).append(v); encoderForArray(4, v.length, offset, expectedLength).append(v);
} }
/** /**
* Encodes an array of floats. * Encodes an array of floats.
*/ */
public void encode(float[] v, int offset) { public void encode(float[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encoderForArray(4, v.length, offset).append(v); encoderForArray(4, v.length, offset, expectedLength).append(v);
} }
/** /**
* Encodes an array of longs. * Encodes an array of longs.
*/ */
public void encode(long[] v, int offset) { public void encode(long[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encoderForArray(8, v.length, offset).append(v); encoderForArray(8, v.length, offset, expectedLength).append(v);
} }
/** /**
* Encodes an array of doubles. * Encodes an array of doubles.
*/ */
public void encode(double[] v, int offset) { public void encode(double[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
encoderForArray(8, v.length, offset).append(v); encoderForArray(8, v.length, offset, expectedLength).append(v);
} }
/** /**
* Encodes an array of {@link Handle}. * Encodes an array of {@link Handle}.
*/ */
public void encode(Handle[] v, int offset) { public void encode(Handle[] v, int offset, int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
Encoder e = encoderForArray(BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset); Encoder e = encoderForArray(
BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset, expectedLength);
for (int i = 0; i < v.length; ++i) { for (int i = 0; i < v.length; ++i) {
e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i); e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
} }
...@@ -393,13 +403,14 @@ public class Encoder { ...@@ -393,13 +403,14 @@ public class Encoder {
/** /**
* Encodes an array of {@link Interface}. * Encodes an array of {@link Interface}.
*/ */
public <T extends Interface> void encode(T[] v, int offset, public <T extends Interface> void encode(T[] v, int offset, int expectedLength,
Interface.Manager<T, ?> manager) { Interface.Manager<T, ?> manager) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
Encoder e = encoderForArray(BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset); Encoder e = encoderForArray(
BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset, expectedLength);
for (int i = 0; i < v.length; ++i) { for (int i = 0; i < v.length; ++i) {
e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
manager); manager);
...@@ -409,12 +420,14 @@ public class Encoder { ...@@ -409,12 +420,14 @@ public class Encoder {
/** /**
* Encodes an array of {@link InterfaceRequest}. * Encodes an array of {@link InterfaceRequest}.
*/ */
public <I extends Interface> void encode(InterfaceRequest<I>[] v, int offset) { public <I extends Interface> void encode(InterfaceRequest<I>[] v, int offset,
int expectedLength) {
if (v == null) { if (v == null) {
encodeNullPointer(offset); encodeNullPointer(offset);
return; return;
} }
Encoder e = encoderForArray(BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset); Encoder e = encoderForArray(
BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset, expectedLength);
for (int i = 0; i < v.length; ++i) { for (int i = 0; i < v.length; ++i) {
e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i); e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
} }
...@@ -431,7 +444,12 @@ public class Encoder { ...@@ -431,7 +444,12 @@ public class Encoder {
encode((long) mEncoderState.dataEnd - (mBaseOffset + offset), offset); encode((long) mEncoderState.dataEnd - (mBaseOffset + offset), offset);
} }
private Encoder encoderForArray(int elementSizeInByte, int length, int offset) { private Encoder encoderForArray(
int elementSizeInByte, int length, int offset, int expectedLength) {
if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH &&
expectedLength != length) {
throw new SerializationException("Trying to encode a fixed array of incorrect length.");
}
return encoderForArrayByTotalSize(length * elementSizeInByte, length, offset); return encoderForArrayByTotalSize(length * elementSizeInByte, length, offset);
} }
......
// 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.
package org.chromium.mojo.bindings;
/**
* Error that can be thrown when serializing a mojo message.
*/
public class SerializationException extends RuntimeException {
/**
* Constructs a new serialization exception with the specified detail message.
*/
public SerializationException(String message) {
super(message);
}
/**
* Constructs a new serialization exception with the specified cause.
*/
public SerializationException(Exception cause) {
super(cause);
}
}
{% from "constant_definition.tmpl" import constant_def %} {% from "constant_definition.tmpl" import constant_def %}
{% from "enum_definition.tmpl" import enum_def %} {% from "enum_definition.tmpl" import enum_def %}
{%- macro array_expected_length(kind) -%}
{%- if kind|is_fixed_array_kind -%}
{{kind.length}}
{%- else -%}
org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
{%- endif -%}
{%- endmacro -%}
{% macro encode(variable, kind, offset, bit, level=0) %} {% macro encode(variable, kind, offset, bit, level=0) %}
{% if kind|is_pointer_array_kind %} {% if kind|is_pointer_array_kind %}
{% set sub_kind = kind.kind %} {% set sub_kind = kind.kind %}
if ({{variable}} == null) { if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}); encoder{{level}}.encodeNullPointer({{offset}});
} else { } else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}); org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{array_expected_length(kind)}});
for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) { for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
{{encode(variable~'[i'~level~']', sub_kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~level, 0, level+1)|indent(8)}} {{encode(variable~'[i'~level~']', sub_kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~level, 0, level+1)|indent(8)}}
} }
...@@ -26,7 +34,7 @@ org.chromium.mojo.bindings.Decoder decoder{{level+1}} = decoder{{level}}.readPoi ...@@ -26,7 +34,7 @@ org.chromium.mojo.bindings.Decoder decoder{{level+1}} = decoder{{level}}.readPoi
if (decoder{{level+1}} == null) { if (decoder{{level+1}} == null) {
{{variable}} = null; {{variable}} = null;
} else { } else {
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeader(); DataHeader si{{level+1}} = decoder{{level+1}}.readArrayDataHeader({{array_expected_length(kind)}});
{{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}}; {{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}};
for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) { for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) {
{{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}} {{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}}
......
...@@ -186,6 +186,12 @@ def DecodeMethod(context, kind, offset, bit): ...@@ -186,6 +186,12 @@ def DecodeMethod(context, kind, offset, bit):
params.append(GetArrayNullabilityFlags(kind)) params.append(GetArrayNullabilityFlags(kind))
else: else:
params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind))) params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind)))
if mojom.IsAnyArrayKind(kind):
if mojom.IsFixedArrayKind(kind):
params.append(str(kind.length))
else:
params.append(
"org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH");
if mojom.IsInterfaceKind(kind): if mojom.IsInterfaceKind(kind):
params.append('%s.MANAGER' % GetJavaType(context, kind)) params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind): if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
...@@ -197,6 +203,12 @@ def EncodeMethod(context, kind, variable, offset, bit): ...@@ -197,6 +203,12 @@ def EncodeMethod(context, kind, variable, offset, bit):
params = [ variable, str(offset) ] params = [ variable, str(offset) ]
if (kind == mojom.BOOL): if (kind == mojom.BOOL):
params.append(str(bit)) params.append(str(bit))
if mojom.IsAnyArrayKind(kind):
if mojom.IsFixedArrayKind(kind):
params.append(str(kind.length))
else:
params.append(
"org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH");
if mojom.IsInterfaceKind(kind): if mojom.IsInterfaceKind(kind):
params.append('%s.MANAGER' % GetJavaType(context, kind)) params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind): if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
...@@ -357,6 +369,7 @@ class Generator(generator.Generator): ...@@ -357,6 +369,7 @@ class Generator(generator.Generator):
"encode_method": EncodeMethod, "encode_method": EncodeMethod,
"has_method_with_response": HasMethodWithResponse, "has_method_with_response": HasMethodWithResponse,
"has_method_without_response": HasMethodWithoutResponse, "has_method_without_response": HasMethodWithoutResponse,
"is_fixed_array_kind": mojom.IsFixedArrayKind,
"is_handle": mojom.IsNonInterfaceHandleKind, "is_handle": mojom.IsNonInterfaceHandleKind,
"is_nullable_kind": mojom.IsNullableKind, "is_nullable_kind": mojom.IsNullableKind,
"is_pointer_array_kind": IsPointerArrayKind, "is_pointer_array_kind": IsPointerArrayKind,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment