Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Unified Diff: ppapi/proxy/raw_var_data.cc

Issue 16140011: Don't send PP_Vars/V8 values with cycles across PostMessage (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ppapi/proxy/raw_var_data.cc
diff --git a/ppapi/proxy/raw_var_data.cc b/ppapi/proxy/raw_var_data.cc
index d4ad2799010d650cb1d3100cd8f757e02d82063d..557fe9756935f3f31e589cc61e1d4b65b0ce1eb3 100644
--- a/ppapi/proxy/raw_var_data.cc
+++ b/ppapi/proxy/raw_var_data.cc
@@ -35,21 +35,29 @@ void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
IPC::ParamTraits<SerializedHandle>::Write(m, handle);
}
+struct StackEntry {
+ StackEntry(PP_Var v, size_t i) : var(v), data_index(i), sentinel(false) {}
+ PP_Var var;
+ size_t data_index;
+ // Used to track parent nodes on the stack while traversing the graph.
+ bool sentinel;
+};
+
// For a given PP_Var, returns the RawVarData associated with it, or creates a
// new one if there is no existing one. The data is appended to |data| if it
// is newly created. The index into |data| pointing to the result is returned.
-// |id_map| keeps track of RawVarDatas that have already been created.
+// |visited_map| keeps track of RawVarDatas that have already been created.
size_t GetOrCreateRawVarData(const PP_Var& var,
- base::hash_map<int64_t, size_t>* id_map,
+ base::hash_map<int64_t, size_t>* visited_map,
ScopedVector<RawVarData>* data) {
if (VarTracker::IsVarTypeRefcounted(var.type)) {
- base::hash_map<int64_t, size_t>::iterator it = id_map->find(
+ base::hash_map<int64_t, size_t>::iterator it = visited_map->find(
var.value.as_id);
- if (it != id_map->end()) {
+ if (it != visited_map->end()) {
return it->second;
} else {
data->push_back(RawVarData::Create(var.type));
- (*id_map)[var.value.as_id] = data->size() - 1;
+ (*visited_map)[var.value.as_id] = data->size() - 1;
}
} else {
data->push_back(RawVarData::Create(var.type));
@@ -71,21 +79,33 @@ scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
PP_Instance instance) {
scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
dmichael (off chromium) 2013/06/05 17:05:47 Looking at this algorithm again, it seems like it
raymes 2013/06/05 22:48:26 I agree that it's not the easiest to understand. T
// Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
- base::hash_map<int64_t, size_t> id_map;
+ base::hash_map<int64_t, size_t> visited_map;
+ base::hash_set<int64_t> parent_ids;
- std::stack<std::pair<PP_Var, size_t> > stack;
- stack.push(make_pair(var, GetOrCreateRawVarData(var, &id_map,
- &graph->data_)));
+ std::stack<StackEntry> stack;
+ stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
+ &graph->data_)));
// Traverse the PP_Var graph with DFS.
while (!stack.empty()) {
- PP_Var current_var = stack.top().first;
- RawVarData* current_var_data = graph->data_[stack.top().second];
- stack.pop();
+ PP_Var current_var = stack.top().var;
+ RawVarData* current_var_data = graph->data_[stack.top().data_index];
+
+ if (stack.top().sentinel) {
dmichael (off chromium) 2013/06/05 17:05:47 Can you avoid adding the new "sentinel" thing by j
raymes 2013/06/05 22:48:26 Yes, good catch.
+ stack.pop();
+ if (::ppapi::VarTracker::IsVarTypeRefcounted(current_var.type))
+ parent_ids.erase(current_var.value.as_id);
dmichael (off chromium) 2013/06/05 17:05:47 Here, if you only put in types that can have child
raymes 2013/06/05 22:48:26 But then the base case changes (i.e. you have to m
+ continue;
+ } else {
+ stack.top().sentinel = true;
+ if (::ppapi::VarTracker::IsVarTypeRefcounted(current_var.type))
+ parent_ids.insert(current_var.value.as_id);
+ }
- // If the node is initialized, it means we have visited it.
- if (current_var_data->initialized())
+ // If the node is initialized, it means we have visited it already.
+ if (current_var_data->initialized()) {
continue;
+ }
if (!current_var_data->Init(current_var, instance)) {
NOTREACHED();
@@ -103,10 +123,15 @@ scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
array_var->elements().begin();
iter != array_var->elements().end();
++iter) {
- size_t child_id = GetOrCreateRawVarData(iter->get(), &id_map,
+ const PP_Var& child = iter->get();
+ if (::ppapi::VarTracker::IsVarTypeRefcounted(child.type) &&
+ parent_ids.count(child.value.as_id) != 0) {
dmichael (off chromium) 2013/06/05 17:05:47 How about an explicit comment here (and below) tha
raymes 2013/06/05 22:48:26 Done.
+ return scoped_ptr<RawVarDataGraph>();
+ }
+ size_t child_id = GetOrCreateRawVarData(child, &visited_map,
&graph->data_);
static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
- stack.push(make_pair(iter->get(), child_id));
+ stack.push(StackEntry(child, child_id));
dmichael (off chromium) 2013/06/05 17:05:47 How about checking at this point whether or not: 1
raymes 2013/06/05 22:48:26 Even if the node doesn't have children, it has to
}
} else if (current_var.type == PP_VARTYPE_DICTIONARY) {
DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
@@ -118,11 +143,16 @@ scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
dict_var->key_value_map().begin();
iter != dict_var->key_value_map().end();
++iter) {
- size_t child_id = GetOrCreateRawVarData(iter->second.get(), &id_map,
+ const PP_Var& child = iter->second.get();
+ if (::ppapi::VarTracker::IsVarTypeRefcounted(child.type) &&
+ parent_ids.count(child.value.as_id) != 0) {
+ return scoped_ptr<RawVarDataGraph>();
+ }
+ size_t child_id = GetOrCreateRawVarData(child, &visited_map,
&graph->data_);
static_cast<DictionaryRawVarData*>(
current_var_data)->AddChild(iter->first, child_id);
- stack.push(make_pair(iter->second.get(), child_id));
+ stack.push(StackEntry(child, child_id));
}
}
}

Powered by Google App Engine
This is Rietveld 408576698