diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-21 17:28:16 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-21 17:28:16 +0000 |
commit | 1162a6aa785238a562f59287b2911cbeb3510955 (patch) | |
tree | 78253eeff401afd8cd5aa312f3664efd095f139f | |
parent | cc057b01668c93e6c769e709c429d1a0c8f15065 (diff) | |
download | chromium_src-1162a6aa785238a562f59287b2911cbeb3510955.zip chromium_src-1162a6aa785238a562f59287b2911cbeb3510955.tar.gz chromium_src-1162a6aa785238a562f59287b2911cbeb3510955.tar.bz2 |
Properly serialize FileRef_CreateInfo vectors. This has the same serialization
problem as vectors of SerializedVars.
TEST=manual
BUG=none
Review URL: http://codereview.chromium.org/6879101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82507 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ppapi/proxy/ppapi_param_traits.cc | 116 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_param_traits.h | 8 |
2 files changed, 89 insertions, 35 deletions
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc index ae447eb..420809f 100644 --- a/ppapi/proxy/ppapi_param_traits.cc +++ b/ppapi/proxy/ppapi_param_traits.cc @@ -16,6 +16,63 @@ namespace IPC { +namespace { + +// Deserializes a vector from IPC. This special version must be used instead +// of the default IPC version when the vector contains a SerializedVar, either +// directly or indirectly (i.e. a vector of objects that have a SerializedVar +// inside them). +// +// The default vector deserializer does resize and then we deserialize into +// those allocated slots. However, the implementation of vector (at least in +// GCC's implementation), creates a new empty object using the default +// constructor, and then sets the rest of the items to that empty one using the +// copy constructor. +// +// Since we allocate the inner class when you call the default constructor and +// transfer the inner class when you do operator=, the entire vector will end +// up referring to the same inner class. Deserializing into this will just end +// up overwriting the same item over and over, since all the SerializedVars +// will refer to the same thing. +// +// The solution is to make a new object for each deserialized item, and then +// add it to the vector one at a time. +template<typename T> +bool ReadVectorWithoutCopy(const Message* m, + void** iter, + std::vector<T>* output) { + // This part is just a copy of the the default ParamTraits vector Read(). + int size; + // ReadLength() checks for < 0 itself. + if (!m->ReadLength(iter, &size)) + return false; + // Resizing beforehand is not safe, see BUG 1006367 for details. + if (INT_MAX / sizeof(T) <= static_cast<size_t>(size)) + return false; + + output->reserve(size); + for (int i = 0; i < size; i++) { + T cur; + if (!ReadParam(m, iter, &cur)) + return false; + output->push_back(cur); + } + return true; +} + +// This serializes the vector of items to the IPC message in exactly the same +// way as the "regular" IPC vector serializer does. But having the code here +// saves us from having to copy this code into all ParamTraits that use the +// ReadVectorWithoutCopy function for deserializing. +template<typename T> +void WriteVectorWithoutCopy(Message* m, const std::vector<T>& p) { + WriteParam(m, static_cast<int>(p.size())); + for (size_t i = 0; i < p.size(); i++) + WriteParam(m, p[i]); +} + +} // namespace + // PP_Bool --------------------------------------------------------------------- // static @@ -397,9 +454,7 @@ void ParamTraits<pp::proxy::SerializedVar>::Log(const param_type& p, void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Write( Message* m, const param_type& p) { - WriteParam(m, static_cast<int>(p.size())); - for (size_t i = 0; i < p.size(); i++) - WriteParam(m, p[i]); + WriteVectorWithoutCopy(m, p); } // static @@ -407,38 +462,7 @@ bool ParamTraits< std::vector<pp::proxy::SerializedVar> >::Read( const Message* m, void** iter, param_type* r) { - // This part is just a copy of the the default ParamTraits vector Read(). - int size; - // ReadLength() checks for < 0 itself. - if (!m->ReadLength(iter, &size)) - return false; - // Resizing beforehand is not safe, see BUG 1006367 for details. - if (INT_MAX / sizeof(pp::proxy::SerializedVar) <= static_cast<size_t>(size)) - return false; - - // The default vector deserializer does resize here and then we deserialize - // into those allocated slots. However, the implementation of vector (at - // least in GCC's implementation), creates a new empty object using the - // default constructor, and then sets the rest of the items to that empty - // one using the copy constructor. - // - // Since we allocate the inner class when you call the default constructor - // and transfer the inner class when you do operator=, the entire vector - // will end up referring to the same inner class. Deserializing into this - // will just end up overwriting the same item over and over, since all the - // SerializedVars will refer to the same thing. - // - // The solution is to make a new SerializedVar for each deserialized item, - // and then add it to the vector one at a time. Our copies are efficient so - // this is no big deal. - r->reserve(size); - for (int i = 0; i < size; i++) { - pp::proxy::SerializedVar var; - if (!ReadParam(m, iter, &var)) - return false; - r->push_back(var); - } - return true; + return ReadVectorWithoutCopy(m, iter, r); } // static @@ -447,6 +471,28 @@ void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Log( std::string* l) { } +// std::vector<PPBFileRef_CreateInfo> ------------------------------------------ + +void ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Write( + Message* m, + const param_type& p) { + WriteVectorWithoutCopy(m, p); +} + +// static +bool ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Read( + const Message* m, + void** iter, + param_type* r) { + return ReadVectorWithoutCopy(m, iter, r); +} + +// static +void ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Log( + const param_type& p, + std::string* l) { +} + // SerializedFlashMenu --------------------------------------------------------- // static diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h index be8f6e4..2d07191 100644 --- a/ppapi/proxy/ppapi_param_traits.h +++ b/ppapi/proxy/ppapi_param_traits.h @@ -139,6 +139,14 @@ struct ParamTraits< std::vector<pp::proxy::SerializedVar> > { }; template<> +struct ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> > { + typedef std::vector<pp::proxy::PPBFileRef_CreateInfo> param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, void** iter, param_type* r); + static void Log(const param_type& p, std::string* l); +}; + +template<> struct ParamTraits<pp::proxy::SerializedFlashMenu> { typedef pp::proxy::SerializedFlashMenu param_type; static void Write(Message* m, const param_type& p); |