Commit f732ce65 authored by yzshen's avatar yzshen Committed by Commit bot

Mojo C++ bindings: fix inlined union validation.

Previously the code couldn't correctly validate inlined nullable unions.

BUG=None.

Review-Url: https://codereview.chromium.org/2286513002
Cr-Commit-Position: refs/heads/master@{#414662}
parent c57af77d
...@@ -46,20 +46,17 @@ bool ValidateStructHeaderAndClaimMemory(const void* data, ...@@ -46,20 +46,17 @@ bool ValidateStructHeaderAndClaimMemory(const void* data,
return true; return true;
} }
bool ValidateUnionHeaderAndClaimMemory(const void* data, bool ValidateNonInlinedUnionHeaderAndClaimMemory(
bool inlined, const void* data,
ValidationContext* validation_context) { ValidationContext* validation_context) {
if (!IsAligned(data)) { if (!IsAligned(data)) {
ReportValidationError(validation_context, ReportValidationError(validation_context,
VALIDATION_ERROR_MISALIGNED_OBJECT); VALIDATION_ERROR_MISALIGNED_OBJECT);
return false; return false;
} }
// If the union is inlined in another structure its memory was already if (!validation_context->ClaimMemory(data, kUnionDataSize) ||
// claimed. *static_cast<const uint32_t*>(data) != kUnionDataSize) {
// This ONLY applies to the union itself, NOT anything which the union points
// to.
if (!inlined && !validation_context->ClaimMemory(data, kUnionDataSize)) {
ReportValidationError(validation_context, ReportValidationError(validation_context,
VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
return false; return false;
......
...@@ -50,12 +50,12 @@ bool ValidateStructHeaderAndClaimMemory(const void* data, ...@@ -50,12 +50,12 @@ bool ValidateStructHeaderAndClaimMemory(const void* data,
ValidationContext* validation_context); ValidationContext* validation_context);
// Validates that |data| contains a valid union header, in terms of alignment // Validates that |data| contains a valid union header, in terms of alignment
// and size. If not inlined, it checks that the memory range // and size. It checks that the memory range [data, data + kUnionDataSize) is
// [data, data + num_bytes) is not marked as occupied by other objects in // not marked as occupied by other objects in |validation_context|. On success,
// |validation_context|. On success, the memory range is marked as occupied. // the memory range is marked as occupied.
bool ValidateUnionHeaderAndClaimMemory(const void* data, bool ValidateNonInlinedUnionHeaderAndClaimMemory(
bool inlined, const void* data,
ValidationContext* validation_context); ValidationContext* validation_context);
// Validates that the message is a request which doesn't expect a response. // Validates that the message is a request which doesn't expect a response.
bool ValidateMessageIsRequestWithoutResponse( bool ValidateMessageIsRequestWithoutResponse(
......
[dist4]message_header // num_bytes
[u4]0 // version
[u4]0 // interface ID
[u4]18 // name
[u4]0 // flags
[u4]0 // padding
[anchr]message_header
[dist4]method18_params // num_bytes
[u4]0 // version
[u4]0 // param0: Size 0 indicating the inlined union is null.
[u4]0 // param0: Tag field ignored.
[u8]0 // param0: Payload field ignored.
[anchr]method18_params
...@@ -56,6 +56,11 @@ enum EnumB { ...@@ -56,6 +56,11 @@ enum EnumB {
ENUM_B_2 ENUM_B_2
}; };
union UnionA {
StructA struct_a;
bool b;
};
// This interface is used for testing bounds-checking in the mojom // This interface is used for testing bounds-checking in the mojom
// binding code. If you add a method please update the files // binding code. If you add a method please update the files
// ./data/validation/boundscheck_*. If you add a response please update // ./data/validation/boundscheck_*. If you add a response please update
...@@ -84,6 +89,7 @@ interface ConformanceTestInterface { ...@@ -84,6 +89,7 @@ interface ConformanceTestInterface {
Method15(array<EnumA>? param0, array<EnumB>? param1); Method15(array<EnumA>? param0, array<EnumB>? param1);
Method16(map<EnumA, EnumA>? param0); Method16(map<EnumA, EnumA>? param0);
Method17(array<InterfaceA> param0); Method17(array<InterfaceA> param0);
Method18(UnionA? param0);
}; };
struct BasicStruct { struct BasicStruct {
......
...@@ -7,15 +7,27 @@ bool {{class_name}}::Validate( ...@@ -7,15 +7,27 @@ bool {{class_name}}::Validate(
const void* data, const void* data,
mojo::internal::ValidationContext* validation_context, mojo::internal::ValidationContext* validation_context,
bool inlined) { bool inlined) {
if (!data) if (!data) {
DCHECK(!inlined);
return true; return true;
}
// If it is inlined, the alignment is already enforced by its enclosing
// object. We don't have to validate that.
DCHECK(!inlined || mojo::internal::IsAligned(data));
if (!ValidateUnionHeaderAndClaimMemory(data, inlined, validation_context)) if (!inlined &&
!mojo::internal::ValidateNonInlinedUnionHeaderAndClaimMemory(
data, validation_context)) {
return false; return false;
}
const {{class_name}}* object = static_cast<const {{class_name}}*>(data); const {{class_name}}* object = static_cast<const {{class_name}}*>(data);
ALLOW_UNUSED_LOCAL(object); ALLOW_UNUSED_LOCAL(object);
if (inlined && object->is_null())
return true;
switch (object->tag) { switch (object->tag) {
{% for field in union.fields %} {% for field in union.fields %}
case {{enum_name}}::{{field.name|upper}}: { case {{enum_name}}::{{field.name|upper}}: {
......
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