Commit 1cb929f1 authored by ppi's avatar ppi Committed by Commit bot

Mojo: validate nullability in Java serialization.

This patch adds nullability validation of handles and
pointers upon struct serialization in the Java bindings.

BUG=324170

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

Cr-Commit-Position: refs/heads/master@{#293120}
parent 9ff8ce36
// 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;
import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
import org.chromium.mojo.HandleMock;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct1;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct2;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct3;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct4;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct5;
import org.chromium.mojo.bindings.test.mojom.mojo.Struct6;
import org.chromium.mojo.bindings.test.mojom.mojo.StructOfNullables;
/**
* Tests for the serialization logic of the generated structs, using structs defined in
* mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom .
*/
public class SerializationTest extends TestCase {
private static void assertThrowsSerializationException(Struct struct) {
try {
struct.serialize(null);
fail("Serialization of invalid struct should have thrown an exception.");
} catch (SerializationException ex) {
// Expected.
}
}
/**
* Verifies that serializing a struct with an invalid handle of a non-nullable type throws an
* exception.
*/
@SmallTest
public void testHandle() {
Struct2 struct = new Struct2();
assertFalse(struct.hdl.isValid());
assertThrowsSerializationException(struct);
// Make the struct valid and verify that it serializes without an exception.
struct.hdl = new HandleMock();
struct.serialize(null);
}
/**
* Verifies that serializing a struct with a null struct pointer throws an exception.
*/
@SmallTest
public void testStructPointer() {
Struct3 struct = new Struct3();
assertNull(struct.struct1);
assertThrowsSerializationException(struct);
// Make the struct valid and verify that it serializes without an exception.
struct.struct1 = new Struct1();
struct.serialize(null);
}
/**
* Verifies that serializing a struct with an array of structs throws an exception when the
* struct is invalid.
*/
@SmallTest
public void testStructArray() {
Struct4 struct = new Struct4();
assertNull(struct.array);
assertThrowsSerializationException(struct);
// Create the (1-element) array but have the element null.
struct.array = new Struct1[1];
assertThrowsSerializationException(struct);
// Create the array element, struct should serialize now.
struct.array[0] = new Struct1();
struct.serialize(null);
}
/**
* Verifies that serializing a struct with a fixed-size array of incorrect length throws an
* exception.
*/
@SmallTest
public void testFixedSizeArray() {
Struct5 struct = new Struct5();
assertNull(struct.pair);
assertThrowsSerializationException(struct);
// Create the (1-element) array, 2-element array is required.
struct.pair = new Struct1[1];
struct.pair[0] = new Struct1();
assertThrowsSerializationException(struct);
// Create the array of a correct size, struct should serialize now.
struct.pair = new Struct1[2];
struct.pair[0] = new Struct1();
struct.pair[1] = new Struct1();
struct.serialize(null);
}
/**
* Verifies that serializing a struct with a null string throws an exception.
*/
@SmallTest
public void testString() {
Struct6 struct = new Struct6();
assertNull(struct.str);
assertThrowsSerializationException(struct);
// Make the struct valid and verify that it serializes without an exception.
struct.str = "";
struct.serialize(null);
}
/**
* Verifies that a struct with an invalid nullable handle, null nullable struct pointer and null
* nullable string serializes without an exception.
*/
@SmallTest
public void testNullableFields() {
StructOfNullables struct = new StructOfNullables();
assertFalse(struct.hdl.isValid());
assertNull(struct.struct1);
assertNull(struct.str);
struct.serialize(null);
}
}
...@@ -29,4 +29,10 @@ struct Struct6 { ...@@ -29,4 +29,10 @@ struct Struct6 {
string str; string str;
}; };
struct StructOfNullables {
handle? hdl;
Struct1? struct_1;
string? str;
};
} }
...@@ -13,7 +13,7 @@ org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH ...@@ -13,7 +13,7 @@ org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
{% 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}}, {{kind|is_nullable_kind|java_true_false}});
} else { } else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{array_expected_length(kind)}}); 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}}) {
......
...@@ -162,20 +162,9 @@ def GetArrayNullabilityFlags(kind): ...@@ -162,20 +162,9 @@ def GetArrayNullabilityFlags(kind):
return " | ".join(flags_to_set) return " | ".join(flags_to_set)
@contextfilter def AppendEncodeDecodeParams(initial_params, context, kind, bit):
def DecodeMethod(context, kind, offset, bit): """ Appends standard parameters shared between encode and decode calls. """
def _DecodeMethodName(kind): params = list(initial_params)
if mojom.IsAnyArrayKind(kind):
return _DecodeMethodName(kind.kind) + 's'
if mojom.IsEnumKind(kind):
return _DecodeMethodName(mojom.INT32)
if mojom.IsInterfaceRequestKind(kind):
return "readInterfaceRequest"
if mojom.IsInterfaceKind(kind):
return "readServiceInterface"
return _spec_to_decode_method[kind.spec]
methodName = _DecodeMethodName(kind)
params = [ str(offset) ]
if (kind == mojom.BOOL): if (kind == mojom.BOOL):
params.append(str(bit)) params.append(str(bit))
if mojom.IsReferenceKind(kind): if mojom.IsReferenceKind(kind):
...@@ -193,23 +182,29 @@ def DecodeMethod(context, kind, offset, bit): ...@@ -193,23 +182,29 @@ def DecodeMethod(context, kind, offset, bit):
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):
params.append('%s.MANAGER' % GetJavaType(context, kind.kind)) params.append('%s.MANAGER' % GetJavaType(context, kind.kind))
return params
@contextfilter
def DecodeMethod(context, kind, offset, bit):
def _DecodeMethodName(kind):
if mojom.IsAnyArrayKind(kind):
return _DecodeMethodName(kind.kind) + 's'
if mojom.IsEnumKind(kind):
return _DecodeMethodName(mojom.INT32)
if mojom.IsInterfaceRequestKind(kind):
return "readInterfaceRequest"
if mojom.IsInterfaceKind(kind):
return "readServiceInterface"
return _spec_to_decode_method[kind.spec]
methodName = _DecodeMethodName(kind)
params = AppendEncodeDecodeParams([ str(offset) ], context, kind, bit)
return '%s(%s)' % (methodName, ', '.join(params)) return '%s(%s)' % (methodName, ', '.join(params))
@contextfilter @contextfilter
def EncodeMethod(context, kind, variable, offset, bit): def EncodeMethod(context, kind, variable, offset, bit):
params = [ variable, str(offset) ] params = AppendEncodeDecodeParams(
if (kind == mojom.BOOL): [ variable, str(offset) ], context, kind, 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):
params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
params.append('%s.MANAGER' % GetJavaType(context, kind.kind))
return 'encode(%s)' % ', '.join(params) return 'encode(%s)' % ', '.join(params)
def GetPackage(module): def GetPackage(module):
......
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