Chromium Code Reviews| Index: webkit/plugins/ppapi/resource_tracker.cc |
| diff --git a/webkit/plugins/ppapi/resource_tracker.cc b/webkit/plugins/ppapi/resource_tracker.cc |
| index 38d55a97424644e57d5e4ad3d24e64c045807bde..f1ce057d4b81aae08bd8956a9a24457165781446 100644 |
| --- a/webkit/plugins/ppapi/resource_tracker.cc |
| +++ b/webkit/plugins/ppapi/resource_tracker.cc |
| @@ -15,6 +15,30 @@ |
| #include "webkit/plugins/ppapi/resource.h" |
| #include "webkit/plugins/ppapi/var.h" |
| +enum PPIdType { |
| + PP_ID_TYPE_MODULE, |
| + PP_ID_TYPE_INSTANCE, |
| + PP_ID_TYPE_RESOURCE, |
| + PP_ID_TYPE_VAR, |
| + PP_ID_TYPE_COUNT |
| +}; |
| + |
| +static const unsigned int kPPIdTypeBits = 2; |
| +COMPILE_ASSERT(PP_ID_TYPE_COUNT <= (1<<kPPIdTypeBits), |
| + kPPIdTypeBits_is_too_small_for_all_id_types); |
| + |
| +template <typename T> static inline T MakeTypedId(T value, PPIdType type) { |
| + return (value << kPPIdTypeBits) | static_cast<T>(type); |
| +} |
| + |
| +template <typename T> static inline bool CheckIdType(T id, PPIdType type) { |
| + // 0 is a valid resource. |
| + if (!id) |
| + return true; |
| + const T mask = (static_cast<T>(1) << kPPIdTypeBits) - 1; |
| + return (id & mask) == type; |
| +} |
| + |
| namespace webkit { |
| namespace ppapi { |
| @@ -22,6 +46,8 @@ static base::LazyInstance<ResourceTracker> g_resource_tracker( |
| base::LINKER_INITIALIZED); |
| scoped_refptr<Resource> ResourceTracker::GetResource(PP_Resource res) const { |
| + DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| + << res << " is not a PP_Resource."; |
| ResourceMap::const_iterator result = live_resources_.find(res); |
| if (result == live_resources_.end()) { |
| return scoped_refptr<Resource>(); |
| @@ -48,30 +74,32 @@ ResourceTracker* ResourceTracker::Get() { |
| } |
| PP_Resource ResourceTracker::AddResource(Resource* resource) { |
| - // If the plugin manages to create 4 billion resources, don't do crazy stuff. |
| - if (last_resource_id_ == std::numeric_limits<PP_Resource>::max()) |
| + // If the plugin manages to create 1 billion resources, don't do crazy stuff. |
| + if (last_resource_id_ == |
| + std::numeric_limits<PP_Resource>::max() >> kPPIdTypeBits) |
|
brettw
2011/01/20 05:45:09
Can you add parens here to clarify the order of op
|
| return 0; |
| // Add the resource with plugin use-count 1. |
| - PP_Resource new_id = ++last_resource_id_; |
| + PP_Resource new_id = MakeTypedId(++last_resource_id_, PP_ID_TYPE_RESOURCE); |
| live_resources_.insert(std::make_pair(new_id, std::make_pair(resource, 1))); |
| instance_to_resources_[resource->instance()->pp_instance()].insert(new_id); |
| return new_id; |
| } |
| int32 ResourceTracker::AddVar(Var* var) { |
| - // If the plugin manages to create 4B strings... |
| - if (last_var_id_ == std::numeric_limits<int32>::max()) { |
| + // If the plugin manages to create 1B strings... |
| + if (last_var_id_ == std::numeric_limits<int32>::max() >> kPPIdTypeBits) { |
| return 0; |
| } |
| // Add the resource with plugin use-count 1. |
| - ++last_var_id_; |
| - live_vars_.insert(std::make_pair(last_var_id_, |
| - std::make_pair(var, 1))); |
| - return last_var_id_; |
| + int32 new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR); |
| + live_vars_.insert(std::make_pair(new_id, std::make_pair(var, 1))); |
| + return new_id; |
| } |
| bool ResourceTracker::AddRefResource(PP_Resource res) { |
| + DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| + << res << " is not a PP_Resource."; |
| ResourceMap::iterator i = live_resources_.find(res); |
| if (i != live_resources_.end()) { |
| // We don't protect against overflow, since a plugin as malicious as to ref |
| @@ -85,6 +113,8 @@ bool ResourceTracker::AddRefResource(PP_Resource res) { |
| } |
| bool ResourceTracker::UnrefResource(PP_Resource res) { |
| + DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| + << res << " is not a PP_Resource."; |
| ResourceMap::iterator i = live_resources_.find(res); |
| if (i != live_resources_.end()) { |
| if (!--i->second.second) { |
| @@ -105,6 +135,8 @@ bool ResourceTracker::UnrefResource(PP_Resource res) { |
| } |
| void ResourceTracker::ForceDeletePluginResourceRefs(PP_Resource res) { |
| + DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| + << res << " is not a PP_Resource."; |
| ResourceMap::iterator i = live_resources_.find(res); |
| if (i == live_resources_.end()) |
| return; // Nothing to do. |
| @@ -138,6 +170,8 @@ uint32 ResourceTracker::GetLiveObjectsForModule(PluginModule* module) const { |
| } |
| scoped_refptr<Var> ResourceTracker::GetVar(int32 var_id) const { |
| + DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) |
| + << var_id << " is not a PP_Var ID."; |
| VarMap::const_iterator result = live_vars_.find(var_id); |
| if (result == live_vars_.end()) { |
| return scoped_refptr<Var>(); |
| @@ -146,6 +180,8 @@ scoped_refptr<Var> ResourceTracker::GetVar(int32 var_id) const { |
| } |
| bool ResourceTracker::AddRefVar(int32 var_id) { |
| + DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) |
| + << var_id << " is not a PP_Var ID."; |
| VarMap::iterator i = live_vars_.find(var_id); |
| if (i != live_vars_.end()) { |
| // We don't protect against overflow, since a plugin as malicious as to ref |
| @@ -158,6 +194,8 @@ bool ResourceTracker::AddRefVar(int32 var_id) { |
| } |
| bool ResourceTracker::UnrefVar(int32 var_id) { |
| + DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) |
| + << var_id << " is not a PP_Var ID."; |
| VarMap::iterator i = live_vars_.find(var_id); |
| if (i != live_vars_.end()) { |
| if (!--i->second.second) |
| @@ -184,7 +222,8 @@ PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { |
| // Need to make sure the random number isn't a duplicate or 0. |
| PP_Instance new_instance; |
| do { |
| - new_instance = static_cast<PP_Instance>(base::RandUint64()); |
| + new_instance = MakeTypedId(static_cast<PP_Instance>(base::RandUint64()), |
| + PP_ID_TYPE_INSTANCE); |
| } while (!new_instance || |
| instance_map_.find(new_instance) != instance_map_.end()); |
| instance_map_[new_instance] = instance; |
| @@ -192,6 +231,8 @@ PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { |
| } |
| void ResourceTracker::InstanceDeleted(PP_Instance instance) { |
| + DLOG_IF(ERROR, !CheckIdType(instance, PP_ID_TYPE_INSTANCE)) |
| + << instance << " is not a PP_Instance."; |
| // Force release all plugin references to resources associated with the |
| // deleted instance. |
| ResourceSet& resource_set = instance_to_resources_[instance]; |
| @@ -215,6 +256,8 @@ void ResourceTracker::InstanceDeleted(PP_Instance instance) { |
| } |
| PluginInstance* ResourceTracker::GetInstance(PP_Instance instance) { |
| + DLOG_IF(ERROR, !CheckIdType(instance, PP_ID_TYPE_INSTANCE)) |
| + << instance << " is not a PP_Instance."; |
| InstanceMap::iterator found = instance_map_.find(instance); |
| if (found == instance_map_.end()) |
| return NULL; |
| @@ -232,7 +275,8 @@ PP_Module ResourceTracker::AddModule(PluginModule* module) { |
| // See AddInstance above. |
| PP_Module new_module; |
| do { |
| - new_module = static_cast<PP_Module>(base::RandUint64()); |
| + new_module = MakeTypedId(static_cast<PP_Module>(base::RandUint64()), |
| + PP_ID_TYPE_MODULE); |
| } while (!new_module || |
| module_map_.find(new_module) != module_map_.end()); |
| module_map_[new_module] = module; |
| @@ -240,6 +284,8 @@ PP_Module ResourceTracker::AddModule(PluginModule* module) { |
| } |
| void ResourceTracker::ModuleDeleted(PP_Module module) { |
| + DLOG_IF(ERROR, !CheckIdType(module, PP_ID_TYPE_MODULE)) |
| + << module << " is not a PP_Module."; |
| ModuleMap::iterator found = module_map_.find(module); |
| if (found == module_map_.end()) { |
| NOTREACHED(); |
| @@ -249,6 +295,8 @@ void ResourceTracker::ModuleDeleted(PP_Module module) { |
| } |
| PluginModule* ResourceTracker::GetModule(PP_Module module) { |
| + DLOG_IF(ERROR, !CheckIdType(module, PP_ID_TYPE_MODULE)) |
| + << module << " is not a PP_Module."; |
| ModuleMap::iterator found = module_map_.find(module); |
| if (found == module_map_.end()) |
| return NULL; |