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

Side by Side Diff: content/child/v8_value_converter_impl.cc

Issue 1939233002: Properly detect cycles in V8ValueConverter, current impl is too strict. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix test, some nits Created 4 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/child/v8_value_converter_impl.h" 5 #include "content/child/v8_value_converter_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <cmath> 10 #include <cmath>
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 : max_recursion_depth_(kMaxRecursionDepth), 84 : max_recursion_depth_(kMaxRecursionDepth),
85 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {} 85 avoid_identity_hash_for_testing_(avoid_identity_hash_for_testing) {}
86 86
87 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and 87 // If |handle| is not in |unique_map_|, then add it to |unique_map_| and
88 // return true. 88 // return true.
89 // 89 //
90 // Otherwise do nothing and return false. Here "A is unique" means that no 90 // Otherwise do nothing and return false. Here "A is unique" means that no
91 // other handle B in the map points to the same object as A. Note that A can 91 // other handle B in the map points to the same object as A. Note that A can
92 // be unique even if there already is another handle with the same identity 92 // be unique even if there already is another handle with the same identity
93 // hash (key) in the map, because two objects can have the same hash. 93 // hash (key) in the map, because two objects can have the same hash.
94 bool UpdateAndCheckUniqueness(v8::Local<v8::Object> handle) { 94 bool AddToUniquenessCheck(v8::Local<v8::Object> handle) {
95 typedef HashToHandleMap::const_iterator Iterator; 95 typedef HashToHandleMap::const_iterator Iterator;
96 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash(); 96 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash();
97 // We only compare using == with handles to objects with the same identity 97 // We only compare using == with handles to objects with the same identity
98 // hash. Different hash obviously means different objects, but two objects 98 // hash. Different hash obviously means different objects, but two objects
99 // in a couple of thousands could have the same identity hash. 99 // in a couple of thousands could have the same identity hash.
100 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash); 100 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash);
101 for (Iterator it = range.first; it != range.second; ++it) { 101 for (Iterator it = range.first; it != range.second; ++it) {
102 // Operator == for handles actually compares the underlying objects. 102 // Operator == for handles actually compares the underlying objects.
103 if (it->second == handle) 103 if (it->second == handle)
104 return false; 104 return false;
105 } 105 }
106 unique_map_.insert(std::make_pair(hash, handle)); 106 unique_map_.insert(std::make_pair(hash, handle));
107 return true; 107 return true;
108 } 108 }
109 109
110 bool RemoveFromUniquenessCheck(v8::Local<v8::Object> handle) {
111 typedef HashToHandleMap::const_iterator Iterator;
112 int hash = avoid_identity_hash_for_testing_ ? 0 : handle->GetIdentityHash();
113 // We only compare using == with handles to objects with the same identity
114 // hash. Different hash obviously means different objects, but two objects
115 // in a couple of thousands could have the same identity hash.
116 std::pair<Iterator, Iterator> range = unique_map_.equal_range(hash);
117 for (Iterator it = range.first; it != range.second; ++it) {
118 // Operator == for handles actually compares the underlying objects.
119 if (it->second == handle) {
120 unique_map_.erase(it);
121 return true;
122 }
123 }
asargent_no_longer_on_chrome 2016/05/03 23:04:58 nit: looks all the above code is duplicated from A
lazyboy 2016/05/03 23:57:49 returning Iterator instead since I'd have lookup t
124 return false;
125 }
126
110 bool HasReachedMaxRecursionDepth() { 127 bool HasReachedMaxRecursionDepth() {
111 return max_recursion_depth_ < 0; 128 return max_recursion_depth_ < 0;
112 } 129 }
113 130
114 private: 131 private:
115 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap; 132 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap;
116 HashToHandleMap unique_map_; 133 HashToHandleMap unique_map_;
117 134
118 int max_recursion_depth_; 135 int max_recursion_depth_;
119 136
120 bool avoid_identity_hash_for_testing_; 137 bool avoid_identity_hash_for_testing_;
138
139 DISALLOW_COPY_AND_ASSIGN(FromV8ValueState);
140 };
141
142 // A class to ensure that objects/arrays that are being converted by
143 // this V8ValueConverterImpl do not have cycles.
144 //
145 // An example of cycle: var v = {}; v = {key: v};
146 // Not an example of cycle: var v = {}; a = [v, v]; or w = {a: v, b: v};
147 class V8ValueConverterImpl::ScopedUniquenessGuard {
148 public:
149 ScopedUniquenessGuard(V8ValueConverterImpl::FromV8ValueState* state,
150 v8::Local<v8::Object> value)
151 : state_(state),
152 value_(value),
153 is_valid_(state_->AddToUniquenessCheck(value_)) {}
154 ~ScopedUniquenessGuard() {
155 if (is_valid_) {
156 bool removed = state_->RemoveFromUniquenessCheck(value_);
157 DCHECK(removed);
158 }
159 }
160
161 bool is_valid() const { return is_valid_; }
162
163 private:
164 typedef std::multimap<int, v8::Local<v8::Object> > HashToHandleMap;
165 V8ValueConverterImpl::FromV8ValueState* state_;
166 v8::Local<v8::Object> value_;
167 bool is_valid_;
168
169 DISALLOW_COPY_AND_ASSIGN(ScopedUniquenessGuard);
121 }; 170 };
122 171
123 V8ValueConverter* V8ValueConverter::create() { 172 V8ValueConverter* V8ValueConverter::create() {
124 return new V8ValueConverterImpl(); 173 return new V8ValueConverterImpl();
125 } 174 }
126 175
127 V8ValueConverterImpl::V8ValueConverterImpl() 176 V8ValueConverterImpl::V8ValueConverterImpl()
128 : date_allowed_(false), 177 : date_allowed_(false),
129 reg_exp_allowed_(false), 178 reg_exp_allowed_(false),
130 function_allowed_(false), 179 function_allowed_(false),
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 return FromV8Object(val.As<v8::Object>(), state, isolate); 419 return FromV8Object(val.As<v8::Object>(), state, isolate);
371 420
372 LOG(ERROR) << "Unexpected v8 value type encountered."; 421 LOG(ERROR) << "Unexpected v8 value type encountered.";
373 return NULL; 422 return NULL;
374 } 423 }
375 424
376 base::Value* V8ValueConverterImpl::FromV8Array( 425 base::Value* V8ValueConverterImpl::FromV8Array(
377 v8::Local<v8::Array> val, 426 v8::Local<v8::Array> val,
378 FromV8ValueState* state, 427 FromV8ValueState* state,
379 v8::Isolate* isolate) const { 428 v8::Isolate* isolate) const {
380 if (!state->UpdateAndCheckUniqueness(val)) 429 ScopedUniquenessGuard uniqueness_guard(state, val);
430 if (!uniqueness_guard.is_valid())
381 return base::Value::CreateNullValue().release(); 431 return base::Value::CreateNullValue().release();
382 432
383 std::unique_ptr<v8::Context::Scope> scope; 433 std::unique_ptr<v8::Context::Scope> scope;
384 // If val was created in a different context than our current one, change to 434 // If val was created in a different context than our current one, change to
385 // that context, but change back after val is converted. 435 // that context, but change back after val is converted.
386 if (!val->CreationContext().IsEmpty() && 436 if (!val->CreationContext().IsEmpty() &&
387 val->CreationContext() != isolate->GetCurrentContext()) 437 val->CreationContext() != isolate->GetCurrentContext())
388 scope.reset(new v8::Context::Scope(val->CreationContext())); 438 scope.reset(new v8::Context::Scope(val->CreationContext()));
389 439
390 if (strategy_) { 440 if (strategy_) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 if (data) 505 if (data)
456 return base::BinaryValue::CreateWithCopiedBuffer(data, length); 506 return base::BinaryValue::CreateWithCopiedBuffer(data, length);
457 else 507 else
458 return NULL; 508 return NULL;
459 } 509 }
460 510
461 base::Value* V8ValueConverterImpl::FromV8Object( 511 base::Value* V8ValueConverterImpl::FromV8Object(
462 v8::Local<v8::Object> val, 512 v8::Local<v8::Object> val,
463 FromV8ValueState* state, 513 FromV8ValueState* state,
464 v8::Isolate* isolate) const { 514 v8::Isolate* isolate) const {
465 if (!state->UpdateAndCheckUniqueness(val)) 515 ScopedUniquenessGuard uniqueness_guard(state, val);
516 if (!uniqueness_guard.is_valid())
466 return base::Value::CreateNullValue().release(); 517 return base::Value::CreateNullValue().release();
467 518
468 std::unique_ptr<v8::Context::Scope> scope; 519 std::unique_ptr<v8::Context::Scope> scope;
469 // If val was created in a different context than our current one, change to 520 // If val was created in a different context than our current one, change to
470 // that context, but change back after val is converted. 521 // that context, but change back after val is converted.
471 if (!val->CreationContext().IsEmpty() && 522 if (!val->CreationContext().IsEmpty() &&
472 val->CreationContext() != isolate->GetCurrentContext()) 523 val->CreationContext() != isolate->GetCurrentContext())
473 scope.reset(new v8::Context::Scope(val->CreationContext())); 524 scope.reset(new v8::Context::Scope(val->CreationContext()));
474 525
475 if (strategy_) { 526 if (strategy_) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 continue; 607 continue;
557 608
558 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), 609 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
559 child.release()); 610 child.release());
560 } 611 }
561 612
562 return result.release(); 613 return result.release();
563 } 614 }
564 615
565 } // namespace content 616 } // namespace content
OLDNEW
« no previous file with comments | « content/child/v8_value_converter_impl.h ('k') | content/child/v8_value_converter_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698