summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-27 11:29:33 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-27 11:29:33 +0000
commit62325293fa04319b6d5ba13e656a507c3766dbd4 (patch)
tree802cc30337177287ee8e629f47696b1f7c489293 /mojo
parent87c47f1cf59074de7bf000fcb8df398cabe6949e (diff)
downloadchromium_src-62325293fa04319b6d5ba13e656a507c3766dbd4.zip
chromium_src-62325293fa04319b6d5ba13e656a507c3766dbd4.tar.gz
chromium_src-62325293fa04319b6d5ba13e656a507c3766dbd4.tar.bz2
Convert verification of options structs to use the new user pointer handling (see r285350).
This includes verification of: * MojoCreateMessagePipeOptions * MojoCreateDataPipeOptions * MojoCreateSharedBufferOptions * MojoDuplicateBufferHandleOptions It also revamps options_validation.h completely (and updates tests). R=darin@chromium.org Review URL: https://codereview.chromium.org/414393002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285836 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
-rw-r--r--mojo/system/core.cc15
-rw-r--r--mojo/system/data_pipe.cc41
-rw-r--r--mojo/system/data_pipe.h2
-rw-r--r--mojo/system/data_pipe_unittest.cc59
-rw-r--r--mojo/system/dispatcher.cc4
-rw-r--r--mojo/system/dispatcher.h4
-rw-r--r--mojo/system/dispatcher_unittest.cc3
-rw-r--r--mojo/system/local_data_pipe_unittest.cc55
-rw-r--r--mojo/system/memory.cc39
-rw-r--r--mojo/system/memory.h109
-rw-r--r--mojo/system/message_pipe_dispatcher.cc18
-rw-r--r--mojo/system/message_pipe_dispatcher.h3
-rw-r--r--mojo/system/options_validation.h162
-rw-r--r--mojo/system/options_validation_unittest.cc224
-rw-r--r--mojo/system/shared_buffer_dispatcher.cc40
-rw-r--r--mojo/system/shared_buffer_dispatcher.h7
-rw-r--r--mojo/system/shared_buffer_dispatcher_unittest.cc24
17 files changed, 426 insertions, 383 deletions
diff --git a/mojo/system/core.cc b/mojo/system/core.cc
index 8899434..9b91632 100644
--- a/mojo/system/core.cc
+++ b/mojo/system/core.cc
@@ -149,9 +149,8 @@ MojoResult Core::CreateMessagePipe(
UserPointer<MojoHandle> message_pipe_handle0,
UserPointer<MojoHandle> message_pipe_handle1) {
MojoCreateMessagePipeOptions validated_options = {};
- // This will verify the |options| pointer.
MojoResult result = MessagePipeDispatcher::ValidateCreateOptions(
- options.GetPointerUnsafe(), &validated_options);
+ options, &validated_options);
if (result != MOJO_RESULT_OK)
return result;
@@ -316,9 +315,8 @@ MojoResult Core::CreateDataPipe(
UserPointer<MojoHandle> data_pipe_producer_handle,
UserPointer<MojoHandle> data_pipe_consumer_handle) {
MojoCreateDataPipeOptions validated_options = {};
- // This will verify the |options| pointer.
- MojoResult result = DataPipe::ValidateCreateOptions(
- options.GetPointerUnsafe(), &validated_options);
+ MojoResult result = DataPipe::ValidateCreateOptions(options,
+ &validated_options);
if (result != MOJO_RESULT_OK)
return result;
@@ -424,9 +422,8 @@ MojoResult Core::CreateSharedBuffer(
uint64_t num_bytes,
UserPointer<MojoHandle> shared_buffer_handle) {
MojoCreateSharedBufferOptions validated_options = {};
- // This will verify the |options| pointer.
MojoResult result =
- SharedBufferDispatcher::ValidateCreateOptions(options.GetPointerUnsafe(),
+ SharedBufferDispatcher::ValidateCreateOptions(options,
&validated_options);
if (result != MOJO_RESULT_OK)
return result;
@@ -460,8 +457,8 @@ MojoResult Core::DuplicateBufferHandle(
// Don't verify |options| here; that's the dispatcher's job.
scoped_refptr<Dispatcher> new_dispatcher;
- MojoResult result = dispatcher->DuplicateBufferHandle(
- options.GetPointerUnsafe(), &new_dispatcher);
+ MojoResult result = dispatcher->DuplicateBufferHandle(options,
+ &new_dispatcher);
if (result != MOJO_RESULT_OK)
return result;
diff --git a/mojo/system/data_pipe.cc b/mojo/system/data_pipe.cc
index b0b350f..78e84f8 100644
--- a/mojo/system/data_pipe.cc
+++ b/mojo/system/data_pipe.cc
@@ -29,33 +29,37 @@ const MojoCreateDataPipeOptions DataPipe::kDefaultCreateOptions = {
// static
MojoResult DataPipe::ValidateCreateOptions(
- const MojoCreateDataPipeOptions* in_options,
+ UserPointer<const MojoCreateDataPipeOptions> in_options,
MojoCreateDataPipeOptions* out_options) {
const MojoCreateDataPipeOptionsFlags kKnownFlags =
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD;
*out_options = kDefaultCreateOptions;
- if (!in_options)
+ if (in_options.IsNull())
return MOJO_RESULT_OK;
- MojoResult result =
- ValidateOptionsStructPointerSizeAndFlags<MojoCreateDataPipeOptions>(
- in_options, kKnownFlags, out_options);
- if (result != MOJO_RESULT_OK)
- return result;
+ UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options);
+ if (!reader.is_valid())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader))
+ return MOJO_RESULT_OK;
+ if ((reader.options().flags & ~kKnownFlags))
+ return MOJO_RESULT_UNIMPLEMENTED;
+ out_options->flags = reader.options().flags;
// Checks for fields beyond |flags|:
- if (!HAS_OPTIONS_STRUCT_MEMBER(MojoCreateDataPipeOptions, element_num_bytes,
- in_options))
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes,
+ reader))
return MOJO_RESULT_OK;
- if (in_options->element_num_bytes == 0)
+ if (reader.options().element_num_bytes == 0)
return MOJO_RESULT_INVALID_ARGUMENT;
- out_options->element_num_bytes = in_options->element_num_bytes;
+ out_options->element_num_bytes = reader.options().element_num_bytes;
- if (!HAS_OPTIONS_STRUCT_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes,
- in_options) ||
- in_options->capacity_num_bytes == 0) {
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes,
+ reader) ||
+ reader.options().capacity_num_bytes == 0) {
// Round the default capacity down to a multiple of the element size (but at
// least one element).
out_options->capacity_num_bytes = std::max(
@@ -64,11 +68,11 @@ MojoResult DataPipe::ValidateCreateOptions(
out_options->element_num_bytes);
return MOJO_RESULT_OK;
}
- if (in_options->capacity_num_bytes % out_options->element_num_bytes != 0)
+ if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (in_options->capacity_num_bytes > kMaxDataPipeCapacityBytes)
+ if (reader.options().capacity_num_bytes > kMaxDataPipeCapacityBytes)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
- out_options->capacity_num_bytes = in_options->capacity_num_bytes;
+ out_options->capacity_num_bytes = reader.options().capacity_num_bytes;
return MOJO_RESULT_OK;
}
@@ -399,7 +403,8 @@ DataPipe::DataPipe(bool has_local_producer,
consumer_two_phase_max_num_bytes_read_(0) {
// Check that the passed in options actually are validated.
MojoCreateDataPipeOptions unused ALLOW_UNUSED = { 0 };
- DCHECK_EQ(ValidateCreateOptions(&validated_options, &unused), MOJO_RESULT_OK);
+ DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused),
+ MOJO_RESULT_OK);
}
DataPipe::~DataPipe() {
diff --git a/mojo/system/data_pipe.h b/mojo/system/data_pipe.h
index 0cdaad8..8ead8ba 100644
--- a/mojo/system/data_pipe.h
+++ b/mojo/system/data_pipe.h
@@ -43,7 +43,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe :
// |MojoCreateDataPipeOptions| and will be entirely overwritten on success (it
// may be partly overwritten on failure).
static MojoResult ValidateCreateOptions(
- const MojoCreateDataPipeOptions* in_options,
+ UserPointer<const MojoCreateDataPipeOptions> in_options,
MojoCreateDataPipeOptions* out_options);
// These are called by the producer dispatcher to implement its methods of
diff --git a/mojo/system/data_pipe_unittest.cc b/mojo/system/data_pipe_unittest.cc
index 6aa2ce7..52c09a3 100644
--- a/mojo/system/data_pipe_unittest.cc
+++ b/mojo/system/data_pipe_unittest.cc
@@ -34,7 +34,7 @@ void RevalidateCreateOptions(
MojoCreateDataPipeOptions revalidated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&validated_options,
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&validated_options),
&revalidated_options));
EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
EXPECT_EQ(validated_options.element_num_bytes,
@@ -60,7 +60,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
{
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(NULL, &validated_options));
+ DataPipe::ValidateCreateOptions(NullUserPointer(),
+ &validated_options));
RevalidateCreateOptions(validated_options);
CheckDefaultCapacity(validated_options);
}
@@ -72,7 +73,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
RevalidateCreateOptions(validated_options);
CheckDefaultCapacity(validated_options);
}
@@ -94,7 +96,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
CheckDefaultCapacity(validated_options);
@@ -110,7 +113,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< capacity;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -132,7 +136,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size << ", " << elements;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -152,7 +157,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -171,7 +177,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -193,7 +200,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -213,7 +221,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -232,7 +241,8 @@ TEST(DataPipeTest, ValidateCreateOptionsValid) {
};
MojoCreateDataPipeOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options))
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options))
<< size;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -255,7 +265,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
// Unknown |flags|.
@@ -268,7 +279,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
// Invalid |element_num_bytes|.
@@ -281,7 +293,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
// |element_num_bytes| too big.
{
@@ -293,7 +306,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
{
MojoCreateDataPipeOptions options = {
@@ -304,7 +318,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
// Invalid |capacity_num_bytes|.
@@ -317,7 +332,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
{
MojoCreateDataPipeOptions options = {
@@ -328,7 +344,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
{
MojoCreateDataPipeOptions options = {
@@ -339,7 +356,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
// |capacity_num_bytes| too big.
{
@@ -351,7 +369,8 @@ TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
};
MojoCreateDataPipeOptions unused;
EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(&options, &unused));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &unused));
}
}
diff --git a/mojo/system/dispatcher.cc b/mojo/system/dispatcher.cc
index e802dee..bd42929 100644
--- a/mojo/system/dispatcher.cc
+++ b/mojo/system/dispatcher.cc
@@ -193,7 +193,7 @@ MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
}
MojoResult Dispatcher::DuplicateBufferHandle(
- const MojoDuplicateBufferHandleOptions* options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher) {
base::AutoLock locker(lock_);
if (is_closed_)
@@ -330,7 +330,7 @@ MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
}
MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
- const MojoDuplicateBufferHandleOptions* /*options*/,
+ UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
lock_.AssertAcquired();
DCHECK(!is_closed_);
diff --git a/mojo/system/dispatcher.h b/mojo/system/dispatcher.h
index 143f44e..2aee019 100644
--- a/mojo/system/dispatcher.h
+++ b/mojo/system/dispatcher.h
@@ -110,7 +110,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher :
// |*new_dispatcher| should be null (and will contain the dispatcher for the
// new handle on success).
MojoResult DuplicateBufferHandle(
- const MojoDuplicateBufferHandleOptions* options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher);
MojoResult MapBuffer(uint64_t offset,
uint64_t num_bytes,
@@ -239,7 +239,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher :
MojoReadDataFlags flags);
virtual MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read);
virtual MojoResult DuplicateBufferHandleImplNoLock(
- const MojoDuplicateBufferHandleOptions* options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher);
virtual MojoResult MapBufferImplNoLock(
uint64_t offset,
diff --git a/mojo/system/dispatcher_unittest.cc b/mojo/system/dispatcher_unittest.cc
index cd2b255..45ef9f6 100644
--- a/mojo/system/dispatcher_unittest.cc
+++ b/mojo/system/dispatcher_unittest.cc
@@ -195,7 +195,8 @@ class ThreadSafetyStressThread : public base::SimpleThread {
case DUPLICATE_BUFFER_HANDLE: {
scoped_refptr<Dispatcher> unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->DuplicateBufferHandle(NULL, &unused));
+ dispatcher_->DuplicateBufferHandle(NullUserPointer(),
+ &unused));
break;
}
case MAP_BUFFER: {
diff --git a/mojo/system/local_data_pipe_unittest.cc b/mojo/system/local_data_pipe_unittest.cc
index 28727f7..1047935 100644
--- a/mojo/system/local_data_pipe_unittest.cc
+++ b/mojo/system/local_data_pipe_unittest.cc
@@ -9,7 +9,6 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "mojo/system/data_pipe.h"
-#include "mojo/system/memory.h"
#include "mojo/system/waiter.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,7 +26,8 @@ TEST(LocalDataPipeTest, Creation) {
// Get default options.
MojoCreateDataPipeOptions default_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(NULL, &default_options));
+ DataPipe::ValidateCreateOptions(NullUserPointer(),
+ &default_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(default_options));
dp->ProducerClose();
dp->ConsumerClose();
@@ -43,7 +43,8 @@ TEST(LocalDataPipeTest, Creation) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
@@ -57,7 +58,8 @@ TEST(LocalDataPipeTest, Creation) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
@@ -71,7 +73,8 @@ TEST(LocalDataPipeTest, Creation) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
@@ -86,7 +89,8 @@ TEST(LocalDataPipeTest, Creation) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
@@ -102,7 +106,8 @@ TEST(LocalDataPipeTest, SimpleReadWrite) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -206,7 +211,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
@@ -332,7 +338,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
{
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -521,7 +528,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
@@ -629,7 +637,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
@@ -720,7 +729,8 @@ TEST(LocalDataPipeTest, MayDiscard) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -913,7 +923,8 @@ TEST(LocalDataPipeTest, AllOrNone) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -1073,7 +1084,8 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -1172,7 +1184,8 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -1311,7 +1324,8 @@ TEST(LocalDataPipeTest, WrapAround) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
// This test won't be valid if |ValidateCreateOptions()| decides to give the
// pipe more space.
ASSERT_EQ(100u, validated_options.capacity_num_bytes);
@@ -1395,7 +1409,8 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
// Close producer first, then consumer.
{
@@ -1580,7 +1595,8 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
@@ -1706,7 +1722,8 @@ TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
};
MojoCreateDataPipeOptions validated_options = { 0 };
EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(&options, &validated_options));
+ DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+ &validated_options));
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
diff --git a/mojo/system/memory.cc b/mojo/system/memory.cc
index 160e1e5..b3cb149 100644
--- a/mojo/system/memory.cc
+++ b/mojo/system/memory.cc
@@ -29,7 +29,7 @@ bool IsAligned<8>(const void* pointer) {
#endif
template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper(const void* pointer) {
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) {
CHECK(pointer && IsAligned<alignment>(pointer));
}
@@ -42,11 +42,11 @@ bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper(const void* pointer) {
}
// Explicitly instantiate the sizes we need. Add instantiations as needed.
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper<1, 1>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(
const void*);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper<4, 4>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(
const void*);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper<8, 8>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(
const void*);
template bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper<1, 1>(
const void*);
@@ -60,7 +60,7 @@ template bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper<8, 8>(
// this in particular to check that various Options structs are aligned.
#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
template <>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper<4, 8>(
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 8>(
const void* pointer) {
CHECK(pointer && reinterpret_cast<uintptr_t>(pointer) % 8 == 0);
}
@@ -70,28 +70,43 @@ bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper<4, 8>(
return !!pointer && reinterpret_cast<uintptr_t>(pointer) % 8 == 0;
}
#else
-template MOJO_SYSTEM_IMPL_EXPORT void CheckUserPointerHelper<4, 8>(
+template MOJO_SYSTEM_IMPL_EXPORT void CheckUserPointer<4, 8>(
const void*);
template MOJO_SYSTEM_IMPL_EXPORT bool VerifyUserPointerHelper<4, 8>(
const void*);
#endif
template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper(
- const void* pointer,
- size_t count) {
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCount(const void* pointer,
+ size_t count) {
CHECK_LE(count, std::numeric_limits<size_t>::max() / size);
CHECK(count == 0 || (pointer && IsAligned<alignment>(pointer)));
}
// Explicitly instantiate the sizes we need. Add instantiations as needed.
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper<1, 1>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCount<1, 1>(
const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper<4, 4>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCount<4, 4>(
const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper<8, 8>(
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCount<8, 8>(
const void*, size_t);
+template <size_t alignment>
+void CheckUserPointerWithSize(const void* pointer, size_t size) {
+ // TODO(vtl): If running in kernel mode, do a full verification. For now, just
+ // check that it's non-null and aligned. (A faster user mode implementation is
+ // also possible if this check is skipped.)
+ CHECK(size == 0 || (!!pointer && internal::IsAligned<alignment>(pointer)));
+}
+
+// Explicitly instantiate the sizes we need. Add instantiations as needed.
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithSize<1>(const void*,
+ size_t);
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithSize<4>(const void*,
+ size_t);
+template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithSize<8>(const void*,
+ size_t);
+
template <size_t size, size_t alignment>
bool VerifyUserPointerWithCountHelper(const void* pointer, size_t count) {
if (count > std::numeric_limits<size_t>::max() / size)
diff --git a/mojo/system/memory.h b/mojo/system/memory.h
index 1a6f7ec..512a05d 100644
--- a/mojo/system/memory.h
+++ b/mojo/system/memory.h
@@ -29,13 +29,22 @@ template <typename T> struct VoidToChar { typedef T type; };
template <> struct VoidToChar<void> { typedef char type; };
template <> struct VoidToChar<const void> { typedef const char type; };
+// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
+// a buffer of the given size and alignment (both in bytes).
template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper(const void* pointer);
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer);
+// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
+// a buffer of |count| elements of the given size and alignment (both in bytes).
template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper(
- const void* pointer,
- size_t count);
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCount(const void* pointer,
+ size_t count);
+
+// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
+// a buffer of the given size and alignment (both in bytes).
+template <size_t alignment>
+void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithSize(const void* pointer,
+ size_t size);
// TODO(vtl): Delete all the |Verify...()| things (and replace them with
// |Check...()|.
@@ -54,6 +63,7 @@ bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithCountHelper(
template <typename Type> class UserPointerReader;
template <typename Type> class UserPointerWriter;
template <typename Type> class UserPointerReaderWriter;
+template <class Options> class UserOptionsReader;
// Verify (insofar as possible/necessary) that a |T| can be read from the user
// |pointer|.
@@ -118,14 +128,31 @@ class UserPointer {
return !pointer_;
}
+ // "Reinterpret casts" to a |UserPointer<ToType>|.
+ template <typename ToType>
+ UserPointer<ToType> ReinterpretCast() const {
+ return UserPointer<ToType>(reinterpret_cast<ToType*>(pointer_));
+ }
+
+ // Checks that this pointer points to a valid array (of type |Type|, or just a
+ // buffer if |Type| is |void| or |const void|) of |count| elements (or bytes
+ // if |Type| is |void| or |const void|) in the same way as |GetArray()| and
+ // |PutArray()|.
+ // TODO(vtl): Logically, there should be separate read checks and write
+ // checks.
+ // TODO(vtl): Switch more things to use this.
+ void CheckArray(size_t count) const {
+ internal::CheckUserPointerWithCount<
+ sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(pointer_, count);
+ }
+
// Gets the value (of type |Type|) pointed to by this user pointer. Use this
// when you'd use the rvalue |*user_pointer|, but be aware that this may be
// costly -- so if the value will be used multiple times, you should save it.
//
// (We want to force a copy here, so return |Type| not |const Type&|.)
Type Get() const {
- internal::CheckUserPointerHelper<sizeof(Type),
- MOJO_ALIGNOF(Type)>(pointer_);
+ internal::CheckUserPointer<sizeof(Type), MOJO_ALIGNOF(Type)>(pointer_);
return *pointer_;
}
@@ -135,8 +162,8 @@ class UserPointer {
// you'd do something like |memcpy(destination, user_pointer, count *
// sizeof(Type)|.
void GetArray(typename internal::remove_const<Type>::type* destination,
- size_t count) {
- internal::CheckUserPointerWithCountHelper<
+ size_t count) const {
+ internal::CheckUserPointerWithCount<
sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(pointer_, count);
memcpy(destination, pointer_, count * sizeof(NonVoidType));
}
@@ -163,8 +190,8 @@ class UserPointer {
// (which obviously be correct), but C++03 doesn't allow default function
// template arguments.
void Put(const NonVoidType& value) {
- internal::CheckUserPointerHelper<sizeof(NonVoidType),
- MOJO_ALIGNOF(NonVoidType)>(pointer_);
+ internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(
+ pointer_);
*pointer_ = value;
}
@@ -176,7 +203,7 @@ class UserPointer {
// Note: The same comments about the validity of |Put()| (except for the part
// about |void|) apply here.
void PutArray(const Type* source, size_t count) {
- internal::CheckUserPointerWithCountHelper<
+ internal::CheckUserPointerWithCount<
sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(pointer_, count);
memcpy(pointer_, source, count * sizeof(NonVoidType));
}
@@ -187,13 +214,6 @@ class UserPointer {
static_cast<NonVoidType*>(pointer_) + i));
}
- // TODO(vtl): This is temporary. Get rid of this. (We should pass
- // |UserPointer<>|s along appropriately, or access data in a safe way
- // everywhere.)
- Type* GetPointerUnsafe() const {
- return pointer_;
- }
-
// These provides safe (read-only/write-only/read-and-write) access to a
// |UserPointer<Type>| (probably pointing to an array) using just an ordinary
// pointer (obtained via |GetPointer()|).
@@ -233,8 +253,10 @@ class UserPointer {
private:
friend class UserPointerReader<Type>;
+ friend class UserPointerReader<const Type>;
friend class UserPointerWriter<Type>;
friend class UserPointerReaderWriter<Type>;
+ template <class Options> friend class UserOptionsReader;
Type* pointer_;
// Allow copy and assignment.
@@ -253,19 +275,34 @@ class UserPointerReader {
typedef typename internal::remove_const<Type>::type TypeNoConst;
public:
+ // Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerReader(UserPointer<const Type> user_pointer, size_t count) {
- Init(user_pointer.pointer_, count);
+ Init(user_pointer.pointer_, count, true);
}
UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) {
- Init(user_pointer.pointer_, count);
+ Init(user_pointer.pointer_, count, true);
}
const Type* GetPointer() const { return buffer_.get(); }
private:
- void Init(const Type* user_pointer, size_t count) {
- internal::CheckUserPointerWithCountHelper<
- sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer, count);
+ template <class Options> friend class UserOptionsReader;
+
+ struct NoCheck {};
+ UserPointerReader(NoCheck,
+ UserPointer<const Type> user_pointer,
+ size_t count) {
+ Init(user_pointer.pointer_, count, false);
+ }
+
+ void Init(const Type* user_pointer, size_t count, bool check) {
+ if (count == 0)
+ return;
+
+ if (check) {
+ internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
+ user_pointer, count);
+ }
buffer_.reset(new TypeNoConst[count]);
memcpy(buffer_.get(), user_pointer, count * sizeof(Type));
}
@@ -279,18 +316,21 @@ class UserPointerReader {
template <typename Type>
class UserPointerWriter {
public:
+ // Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerWriter(UserPointer<Type> user_pointer, size_t count)
: user_pointer_(user_pointer),
count_(count) {
- buffer_.reset(new Type[count_]);
- memset(buffer_.get(), 0, count_ * sizeof(Type));
+ if (count_ > 0) {
+ buffer_.reset(new Type[count_]);
+ memset(buffer_.get(), 0, count_ * sizeof(Type));
+ }
}
Type* GetPointer() const { return buffer_.get(); }
void Commit() {
- internal::CheckUserPointerWithCountHelper<
- sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
+ internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
+ user_pointer_.pointer_, count_);
memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
}
@@ -306,21 +346,24 @@ class UserPointerWriter {
template <typename Type>
class UserPointerReaderWriter {
public:
+ // Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count)
: user_pointer_(user_pointer),
count_(count) {
- internal::CheckUserPointerWithCountHelper<
- sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
- buffer_.reset(new Type[count]);
- memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type));
+ if (count_ > 0) {
+ internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
+ user_pointer_.pointer_, count_);
+ buffer_.reset(new Type[count]);
+ memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type));
+ }
}
Type* GetPointer() const { return buffer_.get(); }
size_t GetCount() const { return count_; }
void Commit() {
- internal::CheckUserPointerWithCountHelper<
- sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
+ internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
+ user_pointer_.pointer_, count_);
memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
}
diff --git a/mojo/system/message_pipe_dispatcher.cc b/mojo/system/message_pipe_dispatcher.cc
index 70f3bc3..448b085 100644
--- a/mojo/system/message_pipe_dispatcher.cc
+++ b/mojo/system/message_pipe_dispatcher.cc
@@ -43,20 +43,24 @@ MessagePipeDispatcher::MessagePipeDispatcher(
// static
MojoResult MessagePipeDispatcher::ValidateCreateOptions(
- const MojoCreateMessagePipeOptions* in_options,
+ UserPointer<const MojoCreateMessagePipeOptions> in_options,
MojoCreateMessagePipeOptions* out_options) {
const MojoCreateMessagePipeOptionsFlags kKnownFlags =
MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE;
*out_options = kDefaultCreateOptions;
- if (!in_options)
+ if (in_options.IsNull())
return MOJO_RESULT_OK;
- MojoResult result =
- ValidateOptionsStructPointerSizeAndFlags<MojoCreateMessagePipeOptions>(
- in_options, kKnownFlags, out_options);
- if (result != MOJO_RESULT_OK)
- return result;
+ UserOptionsReader<MojoCreateMessagePipeOptions> reader(in_options);
+ if (!reader.is_valid())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateMessagePipeOptions, flags, reader))
+ return MOJO_RESULT_OK;
+ if ((reader.options().flags & ~kKnownFlags))
+ return MOJO_RESULT_UNIMPLEMENTED;
+ out_options->flags = reader.options().flags;
// Checks for fields beyond |flags|:
diff --git a/mojo/system/message_pipe_dispatcher.h b/mojo/system/message_pipe_dispatcher.h
index e59267a..b06001c 100644
--- a/mojo/system/message_pipe_dispatcher.h
+++ b/mojo/system/message_pipe_dispatcher.h
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "mojo/system/dispatcher.h"
+#include "mojo/system/memory.h"
#include "mojo/system/system_impl_export.h"
namespace mojo {
@@ -37,7 +38,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher : public Dispatcher {
// |MojoCreateMessagePipeOptions| and will be entirely overwritten on success
// (it may be partly overwritten on failure).
static MojoResult ValidateCreateOptions(
- const MojoCreateMessagePipeOptions* in_options,
+ UserPointer<const MojoCreateMessagePipeOptions> in_options,
MojoCreateMessagePipeOptions* out_options);
// Must be called before any other methods. (This method is not thread-safe.)
diff --git a/mojo/system/options_validation.h b/mojo/system/options_validation.h
index 04514ad..90c1568 100644
--- a/mojo/system/options_validation.h
+++ b/mojo/system/options_validation.h
@@ -14,108 +14,88 @@
#include <stddef.h>
#include <stdint.h>
+#include <algorithm>
+
+#include "base/logging.h"
#include "base/macros.h"
#include "mojo/public/c/system/types.h"
+#include "mojo/system/constants.h"
#include "mojo/system/memory.h"
#include "mojo/system/system_impl_export.h"
namespace mojo {
namespace system {
-// Checks that |buffer| appears to contain a valid Options struct, namely
-// properly aligned and with a |struct_size| field (which must the first field
-// of the struct and be a |uint32_t|) containing a plausible size.
-template <class Options>
-bool IsOptionsStructPointerAndSizeValid(const void* buffer) {
- COMPILE_ASSERT(offsetof(Options, struct_size) == 0,
- Options_struct_size_not_first_member);
- // TODO(vtl): With C++11, use |sizeof(Options::struct_size)| instead.
- COMPILE_ASSERT(sizeof(static_cast<const Options*>(buffer)->struct_size) ==
- sizeof(uint32_t),
- Options_struct_size_not_32_bits);
-
- // Note: Use |MOJO_ALIGNOF()| here to match the exact macro used in the
- // declaration of Options structs.
- if (!internal::VerifyUserPointerHelper<sizeof(uint32_t),
- MOJO_ALIGNOF(Options)>(buffer))
- return false;
-
- return static_cast<const Options*>(buffer)->struct_size >= sizeof(uint32_t);
-}
-
-// Checks that the Options struct in |buffer| has a member with the given offset
-// and size. This may be called only if |IsOptionsStructPointerAndSizeValid()|
-// returned true.
-//
-// You may want to use the macro |HAS_OPTIONS_STRUCT_MEMBER()| instead.
-template <class Options, size_t offset, size_t size>
-bool HasOptionsStructMember(const void* buffer) {
- // We assume that |offset| and |size| are reasonable, since they should come
- // from |offsetof(Options, some_member)| and |sizeof(Options::some_member)|,
- // respectively.
- return static_cast<const Options*>(buffer)->struct_size >=
- offset + size;
-}
-
-// Macro to invoke |HasOptionsStructMember()| parametrized by member name
-// instead of offset and size.
-//
-// (We can't just give |HasOptionsStructMember()| a member pointer template
-// argument instead, since there's no good/strictly-correct way to get an offset
-// from that.)
-//
-// TODO(vtl): With C++11, use |sizeof(Options::member)| instead.
-#define HAS_OPTIONS_STRUCT_MEMBER(Options, member, buffer) \
- (HasOptionsStructMember< \
- Options, \
- offsetof(Options, member), \
- sizeof(static_cast<const Options*>(buffer)->member)>(buffer))
-
-// Checks that the (standard) |flags| member consists of only known flags. This
-// should only be called if |HAS_OPTIONS_STRUCT_MEMBER()| returned true for the
-// |flags| field.
-//
-// The rationale for *not* ignoring these flags is that the caller should have a
-// way of specifying that certain options not be ignored. E.g., one may have a
-// |MOJO_..._OPTIONS_FLAG_DONT_IGNORE_FOO| flag and a |foo| member; if the flag
-// is set, it will guarantee that the version of the system knows about the
-// |foo| member (and won't ignore it).
-template <class Options>
-bool AreOptionsFlagsAllKnown(const void* buffer, uint32_t known_flags) {
- return (static_cast<const Options*>(buffer)->flags & ~known_flags) == 0;
-}
-
-// Does basic cursory checks on |in_options| (|struct_size| and |flags|; |flags|
-// must immediately follow |struct_size|); |in_options| must be non-null. The
-// following should be done before calling this:
-// - Set |out_options| to the default options.
-// - If |in_options| is null, don't continue (success).
-// This function then:
-// - Checks if (according to |IsOptionsStructPointerAndSizeValid()|),
-// |struct_size| is valid; if not returns |MOJO_RESULT_INVALID_ARGUMENT|.
-// - If |in_options| has a |flags| field, checks that it only has
-// |known_flags| set; if so copies it to |out_options->flags|, and if not
-// returns |MOJO_RESULT_UNIMPLEMENTED|.
-// - At this point, returns |MOJO_RESULT_OK|.
template <class Options>
-MojoResult ValidateOptionsStructPointerSizeAndFlags(
- const Options* in_options,
- uint32_t known_flags,
- Options* out_options) {
- COMPILE_ASSERT(offsetof(Options, flags) == sizeof(uint32_t),
- Options_flags_doesnt_immediately_follow_struct_size);
-
- if (!IsOptionsStructPointerAndSizeValid<Options>(in_options))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (HAS_OPTIONS_STRUCT_MEMBER(Options, flags, in_options)) {
- if (!AreOptionsFlagsAllKnown<Options>(in_options, known_flags))
- return MOJO_RESULT_UNIMPLEMENTED;
- out_options->flags = in_options->flags;
+class UserOptionsReader {
+ public:
+ // Constructor from a |UserPointer<const Options>| (which it checks -- this
+ // constructor has side effects!).
+ // Note: We initialize |options_reader_| without checking, since we do a check
+ // in |GetSizeForReader()|.
+ explicit UserOptionsReader(UserPointer<const Options> options)
+ : options_reader_(UserPointer<const char>::Reader::NoCheck(),
+ options.template ReinterpretCast<const char>(),
+ GetSizeForReader(options)) {
+ COMPILE_ASSERT(offsetof(Options, struct_size) == 0,
+ Options_struct_size_not_first_member);
+ // TODO(vtl): With C++11, compile-assert that |sizeof(Options::struct_size)
+ // == sizeof(uint32_t)| somewhere.
}
- return MOJO_RESULT_OK;
-}
+ bool is_valid() const {
+ return !!options_reader_.GetPointer();
+ }
+
+ const Options& options() const {
+ DCHECK(is_valid());
+ return *reinterpret_cast<const Options*>(options_reader_.GetPointer());
+ }
+
+ // Checks that the given (variable-size) |options| passed to the constructor
+ // (plausibly) has a member at the given offset with the given size. You
+ // probably want to use |OPTIONS_STRUCT_HAS_MEMBER()| instead.
+ bool HasMember(size_t offset, size_t size) const {
+ DCHECK(is_valid());
+ // We assume that |offset| and |size| are reasonable, since they should come
+ // from |offsetof(Options, some_member)| and |sizeof(Options::some_member)|,
+ // respectively.
+ return options().struct_size >= offset + size;
+ }
+
+ private:
+ static inline size_t GetSizeForReader(UserPointer<const Options> options) {
+ uint32_t struct_size =
+ options.template ReinterpretCast<const uint32_t>().Get();
+ if (struct_size < sizeof(uint32_t))
+ return 0;
+
+ // Check the full requested size.
+ // Note: Use |MOJO_ALIGNOF()| here to match the exact macro used in the
+ // declaration of Options structs.
+ internal::CheckUserPointerWithSize<MOJO_ALIGNOF(Options)>(options.pointer_,
+ struct_size);
+ options.template ReinterpretCast<const char>().CheckArray(struct_size);
+ // But we'll never look at more than |sizeof(Options)| bytes.
+ return std::min(static_cast<size_t>(struct_size), sizeof(Options));
+ }
+
+ UserPointer<const char>::Reader options_reader_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserOptionsReader);
+};
+
+// Macro to invoke |UserOptionsReader<Options>::HasMember()| parametrized by
+// member name instead of offset and size.
+//
+// (We can't just give |HasMember()| a member pointer template argument instead,
+// since there's no good/strictly-correct way to get an offset from that.)
+//
+// TODO(vtl): With C++11, use |sizeof(Options::member)| instead of (the
+// contortion below). We might also be able to pull out the type |Options| from
+// |reader| (using |decltype|) instead of requiring a parameter.
+#define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \
+ reader.HasMember(offsetof(Options, member), sizeof(reader.options().member))
} // namespace system
} // namespace mojo
diff --git a/mojo/system/options_validation_unittest.cc b/mojo/system/options_validation_unittest.cc
index 4a26fc6..615dac80 100644
--- a/mojo/system/options_validation_unittest.cc
+++ b/mojo/system/options_validation_unittest.cc
@@ -30,161 +30,107 @@ MOJO_COMPILE_ASSERT(sizeof(TestOptions) == 16, TestOptions_has_wrong_size);
const uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions));
TEST(OptionsValidationTest, Valid) {
- const TestOptions kOptions1 = {
- kSizeOfTestOptions
- };
-
- EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions1));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions1));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions1));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions1));
-
- const TestOptions kOptions2 = {
- static_cast<uint32_t>(offsetof(TestOptions, struct_size) + sizeof(uint32_t))
- };
- EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions2));
- EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions2));
- EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions2));
- EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions2));
-
- const TestOptions kOptions3 = {
- static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))
- };
- EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions3));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions3));
- EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions3));
- EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions3));
-
- MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
- TestOptions* options = reinterpret_cast<TestOptions*>(buf);
- options->struct_size = kSizeOfTestOptions + 1;
- EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, options));
-
- options->struct_size = kSizeOfTestOptions + 4;
- EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, options));
- EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, options));
-}
-
-TEST(OptionsValidationTest, Invalid) {
- // Null:
- EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(NULL));
-
- // Unaligned:
- EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(
- reinterpret_cast<const void*>(1)));
- EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(
- reinterpret_cast<const void*>(4)));
-
- // Size too small:
- for (size_t i = 0; i < sizeof(uint32_t); i++) {
- TestOptions options = {static_cast<uint32_t>(i)};
- EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(&options))
- << i;
+ {
+ const TestOptions kOptions = {
+ kSizeOfTestOptions
+ };
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
+ EXPECT_TRUE(reader.is_valid());
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
}
-}
-
-TEST(OptionsValidationTest, CheckFlags) {
- const TestOptions kOptions1 = {kSizeOfTestOptions, 0};
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 0u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 1u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 3u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 7u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, ~0u));
-
- const TestOptions kOptions2 = {kSizeOfTestOptions, 1};
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 0u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 1u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 3u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 7u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, ~0u));
-
- const TestOptions kOptions3 = {kSizeOfTestOptions, 2};
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 0u));
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 1u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 3u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 7u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, ~0u));
-
- const TestOptions kOptions4 = {kSizeOfTestOptions, 5};
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 0u));
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 1u));
- EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 3u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 7u));
- EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, ~0u));
-}
-
-TEST(OptionsValidationTest, ValidateOptionsStructPointerSizeAndFlags) {
- const TestOptions kDefaultOptions = {kSizeOfTestOptions, 1u, 123u, 456u};
-
- // Valid cases:
-
- // "Normal":
{
- const TestOptions kOptions = {kSizeOfTestOptions, 0u, 12u, 34u};
- TestOptions validated_options = kDefaultOptions;
- EXPECT_EQ(MOJO_RESULT_OK,
- ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
- &kOptions, 3u, &validated_options));
- EXPECT_EQ(kDefaultOptions.struct_size, validated_options.struct_size);
- // Copied |flags|.
- EXPECT_EQ(kOptions.flags, validated_options.flags);
- // Didn't touch subsequent members.
- EXPECT_EQ(kDefaultOptions.member1, validated_options.member1);
- EXPECT_EQ(kDefaultOptions.member2, validated_options.member2);
+ const TestOptions kOptions = {
+ static_cast<uint32_t>(offsetof(TestOptions, struct_size) +
+ sizeof(uint32_t))
+ };
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
+ EXPECT_TRUE(reader.is_valid());
+ EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
+ EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
+ EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
}
- // Doesn't actually have |flags|:
{
const TestOptions kOptions = {
- static_cast<uint32_t>(sizeof(uint32_t)), 0u, 12u, 34u
+ static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))
};
- TestOptions validated_options = kDefaultOptions;
- EXPECT_EQ(MOJO_RESULT_OK,
- ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
- &kOptions, 3u, &validated_options));
- EXPECT_EQ(kDefaultOptions.struct_size, validated_options.struct_size);
- // Didn't copy |flags|.
- EXPECT_EQ(kDefaultOptions.flags, validated_options.flags);
- // Didn't touch subsequent members.
- EXPECT_EQ(kDefaultOptions.member1, validated_options.member1);
- EXPECT_EQ(kDefaultOptions.member2, validated_options.member2);
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
+ EXPECT_TRUE(reader.is_valid());
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
+ EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
+ EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
}
-
- // Invalid cases:
-
- // Unaligned:
{
- TestOptions validated_options = kDefaultOptions;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
- reinterpret_cast<const TestOptions*>(1), 3u,
- &validated_options));
+ MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
+ TestOptions* options = reinterpret_cast<TestOptions*>(buf);
+ options->struct_size = kSizeOfTestOptions + 1;
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
+ EXPECT_TRUE(reader.is_valid());
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
}
-
- // |struct_size| too small:
{
- const TestOptions kOptions = {1u, 0u, 12u, 34u};
- TestOptions validated_options = kDefaultOptions;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
- &kOptions, 3u, &validated_options));
+ MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
+ TestOptions* options = reinterpret_cast<TestOptions*>(buf);
+ options->struct_size = kSizeOfTestOptions + 4;
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
+ EXPECT_TRUE(reader.is_valid());
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
+ EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
}
+}
- // Unknown |flag|:
- {
- const TestOptions kOptions = {kSizeOfTestOptions, 5u, 12u, 34u};
- TestOptions validated_options = kDefaultOptions;
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
- &kOptions, 3u, &validated_options));
+TEST(OptionsValidationTest, Invalid) {
+ // Size too small:
+ for (size_t i = 0; i < sizeof(uint32_t); i++) {
+ TestOptions options = {static_cast<uint32_t>(i)};
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(&options));
+ EXPECT_FALSE(reader.is_valid()) << i;
}
}
+// These test invalid arguments that should cause death if we're being paranoid
+// about checking arguments (which we would want to do if, e.g., we were in a
+// true "kernel" situation, but we might not want to do otherwise for
+// performance reasons). Probably blatant errors like passing in null pointers
+// (for required pointer arguments) will still cause death, but perhaps not
+// predictably.
+TEST(OptionsValidationTest, InvalidDeath) {
+ const char kMemoryCheckFailedRegex[] = "Check failed";
+
+ // Null:
+ EXPECT_DEATH_IF_SUPPORTED(
+ { UserOptionsReader<TestOptions> reader((NullUserPointer())); },
+ kMemoryCheckFailedRegex);
+
+ // Unaligned:
+ EXPECT_DEATH_IF_SUPPORTED(
+ { UserOptionsReader<TestOptions> reader(
+ MakeUserPointer(reinterpret_cast<const TestOptions*>(1))); },
+ kMemoryCheckFailedRegex);
+// TODO(vtl): Broken on Windows. Fix this!
+#if 0
+ // Note: The current implementation checks the size only after checking the
+ // alignment versus that required for the |uint32_t| size, so it won't die in
+ // the expected way if you pass, e.g., 4. So we have to manufacture a valid
+ // pointer at an offset of alignment 4.
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ uint32_t buffer[100] = {};
+ TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 4 == 0) ?
+ reinterpret_cast<TestOptions*>(&buffer[1]) :
+ reinterpret_cast<TestOptions*>(&buffer[0]);
+ options->struct_size = static_cast<uint32_t>(sizeof(TestOptions));
+ UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
+ },
+ kMemoryCheckFailedRegex);
+#endif
+}
+
} // namespace
} // namespace system
} // namespace mojo
diff --git a/mojo/system/shared_buffer_dispatcher.cc b/mojo/system/shared_buffer_dispatcher.cc
index 1181b01..375ae7c 100644
--- a/mojo/system/shared_buffer_dispatcher.cc
+++ b/mojo/system/shared_buffer_dispatcher.cc
@@ -35,20 +35,24 @@ const MojoCreateSharedBufferOptions
// static
MojoResult SharedBufferDispatcher::ValidateCreateOptions(
- const MojoCreateSharedBufferOptions* in_options,
+ UserPointer<const MojoCreateSharedBufferOptions> in_options,
MojoCreateSharedBufferOptions* out_options) {
const MojoCreateSharedBufferOptionsFlags kKnownFlags =
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
*out_options = kDefaultCreateOptions;
- if (!in_options)
+ if (in_options.IsNull())
return MOJO_RESULT_OK;
- MojoResult result =
- ValidateOptionsStructPointerSizeAndFlags<MojoCreateSharedBufferOptions>(
- in_options, kKnownFlags, out_options);
- if (result != MOJO_RESULT_OK)
- return result;
+ UserOptionsReader<MojoCreateSharedBufferOptions> reader(in_options);
+ if (!reader.is_valid())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateSharedBufferOptions, flags, reader))
+ return MOJO_RESULT_OK;
+ if ((reader.options().flags & ~kKnownFlags))
+ return MOJO_RESULT_UNIMPLEMENTED;
+ out_options->flags = reader.options().flags;
// Checks for fields beyond |flags|:
@@ -140,7 +144,7 @@ SharedBufferDispatcher::~SharedBufferDispatcher() {
// static
MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
- const MojoDuplicateBufferHandleOptions* in_options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> in_options,
MojoDuplicateBufferHandleOptions* out_options) {
const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
@@ -150,15 +154,19 @@ MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
};
*out_options = kDefaultOptions;
- if (!in_options)
+ if (in_options.IsNull())
return MOJO_RESULT_OK;
- MojoResult result =
- ValidateOptionsStructPointerSizeAndFlags<
- MojoDuplicateBufferHandleOptions>(
- in_options, kKnownFlags, out_options);
- if (result != MOJO_RESULT_OK)
- return result;
+ UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options);
+ if (!reader.is_valid())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags,
+ reader))
+ return MOJO_RESULT_OK;
+ if ((reader.options().flags & ~kKnownFlags))
+ return MOJO_RESULT_UNIMPLEMENTED;
+ out_options->flags = reader.options().flags;
// Checks for fields beyond |flags|:
@@ -183,7 +191,7 @@ scoped_refptr<Dispatcher>
}
MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
- const MojoDuplicateBufferHandleOptions* options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher) {
lock().AssertAcquired();
diff --git a/mojo/system/shared_buffer_dispatcher.h b/mojo/system/shared_buffer_dispatcher.h
index ff251e3..cebef027 100644
--- a/mojo/system/shared_buffer_dispatcher.h
+++ b/mojo/system/shared_buffer_dispatcher.h
@@ -6,6 +6,7 @@
#define MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
#include "base/macros.h"
+#include "mojo/system/memory.h"
#include "mojo/system/raw_shared_buffer.h"
#include "mojo/system/simple_dispatcher.h"
#include "mojo/system/system_impl_export.h"
@@ -28,7 +29,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
// |MojoCreateSharedBufferOptions| and will be entirely overwritten on success
// (it may be partly overwritten on failure).
static MojoResult ValidateCreateOptions(
- const MojoCreateSharedBufferOptions* in_options,
+ UserPointer<const MojoCreateSharedBufferOptions> in_options,
MojoCreateSharedBufferOptions* out_options);
// Static factory method: |validated_options| must be validated (obviously).
@@ -60,7 +61,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
// point to a (current) |MojoDuplicateBufferHandleOptions| and will be
// entirely overwritten on success (it may be partly overwritten on failure).
static MojoResult ValidateDuplicateOptions(
- const MojoDuplicateBufferHandleOptions* in_options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> in_options,
MojoDuplicateBufferHandleOptions* out_options);
// |Dispatcher| protected methods:
@@ -68,7 +69,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
virtual scoped_refptr<Dispatcher>
CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE;
virtual MojoResult DuplicateBufferHandleImplNoLock(
- const MojoDuplicateBufferHandleOptions* options,
+ UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher) OVERRIDE;
virtual MojoResult MapBufferImplNoLock(
uint64_t offset,
diff --git a/mojo/system/shared_buffer_dispatcher_unittest.cc b/mojo/system/shared_buffer_dispatcher_unittest.cc
index 8534ae5..a5198d7 100644
--- a/mojo/system/shared_buffer_dispatcher_unittest.cc
+++ b/mojo/system/shared_buffer_dispatcher_unittest.cc
@@ -34,7 +34,7 @@ void RevalidateCreateOptions(
MojoCreateSharedBufferOptions revalidated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
SharedBufferDispatcher::ValidateCreateOptions(
- &validated_options, &revalidated_options));
+ MakeUserPointer(&validated_options), &revalidated_options));
EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
EXPECT_EQ(validated_options.flags, revalidated_options.flags);
}
@@ -46,7 +46,7 @@ TEST(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
MojoCreateSharedBufferOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
SharedBufferDispatcher::ValidateCreateOptions(
- NULL, &validated_options));
+ NullUserPointer(), &validated_options));
RevalidateCreateOptions(validated_options);
}
@@ -66,7 +66,7 @@ TEST(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
MojoCreateSharedBufferOptions validated_options = {};
EXPECT_EQ(MOJO_RESULT_OK,
SharedBufferDispatcher::ValidateCreateOptions(
- &options, &validated_options))
+ MakeUserPointer(&options), &validated_options))
<< capacity;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -83,7 +83,8 @@ TEST(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
};
MojoCreateSharedBufferOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
+ SharedBufferDispatcher::ValidateCreateOptions(
+ MakeUserPointer(&options), &unused));
}
// Unknown |flags|.
@@ -94,7 +95,8 @@ TEST(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
};
MojoCreateSharedBufferOptions unused;
EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
+ SharedBufferDispatcher::ValidateCreateOptions(
+ MakeUserPointer(&options), &unused));
}
}
@@ -153,7 +155,8 @@ TEST(SharedBufferDispatcher, DuplicateBufferHandle) {
// Duplicate |dispatcher1| and then close it.
scoped_refptr<Dispatcher> dispatcher2;
EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher1->DuplicateBufferHandle(NULL, &dispatcher2));
+ dispatcher1->DuplicateBufferHandle(NullUserPointer(),
+ &dispatcher2));
ASSERT_TRUE(dispatcher2);
EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType());
@@ -183,7 +186,8 @@ TEST(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) {
for (size_t i = 0; i < arraysize(options); i++) {
scoped_refptr<Dispatcher> dispatcher2;
EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher1->DuplicateBufferHandle(&options[i], &dispatcher2));
+ dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options[i]),
+ &dispatcher2));
ASSERT_TRUE(dispatcher2);
EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType());
EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
@@ -206,7 +210,8 @@ TEST(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
};
scoped_refptr<Dispatcher> dispatcher2;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
+ dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options),
+ &dispatcher2));
EXPECT_FALSE(dispatcher2);
}
@@ -217,7 +222,8 @@ TEST(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
};
scoped_refptr<Dispatcher> dispatcher2;
EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
+ dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options),
+ &dispatcher2));
EXPECT_FALSE(dispatcher2);
}