diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-27 11:29:33 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-27 11:29:33 +0000 |
commit | 62325293fa04319b6d5ba13e656a507c3766dbd4 (patch) | |
tree | 802cc30337177287ee8e629f47696b1f7c489293 /mojo | |
parent | 87c47f1cf59074de7bf000fcb8df398cabe6949e (diff) | |
download | chromium_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.cc | 15 | ||||
-rw-r--r-- | mojo/system/data_pipe.cc | 41 | ||||
-rw-r--r-- | mojo/system/data_pipe.h | 2 | ||||
-rw-r--r-- | mojo/system/data_pipe_unittest.cc | 59 | ||||
-rw-r--r-- | mojo/system/dispatcher.cc | 4 | ||||
-rw-r--r-- | mojo/system/dispatcher.h | 4 | ||||
-rw-r--r-- | mojo/system/dispatcher_unittest.cc | 3 | ||||
-rw-r--r-- | mojo/system/local_data_pipe_unittest.cc | 55 | ||||
-rw-r--r-- | mojo/system/memory.cc | 39 | ||||
-rw-r--r-- | mojo/system/memory.h | 109 | ||||
-rw-r--r-- | mojo/system/message_pipe_dispatcher.cc | 18 | ||||
-rw-r--r-- | mojo/system/message_pipe_dispatcher.h | 3 | ||||
-rw-r--r-- | mojo/system/options_validation.h | 162 | ||||
-rw-r--r-- | mojo/system/options_validation_unittest.cc | 224 | ||||
-rw-r--r-- | mojo/system/shared_buffer_dispatcher.cc | 40 | ||||
-rw-r--r-- | mojo/system/shared_buffer_dispatcher.h | 7 | ||||
-rw-r--r-- | mojo/system/shared_buffer_dispatcher_unittest.cc | 24 |
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); } |