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

Side by Side Diff: chrome/renderer/extensions/automation_internal_custom_bindings.cc

Issue 2828773002: Replace v8::Object::Set with CreateDataProperty for security reasons. (Closed)
Patch Set: StringPiece doesn't need to be a reference Created 3 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "chrome/renderer/extensions/automation_internal_custom_bindings.h" 5 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <memory> 10 #include <memory>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/threading/thread_task_runner_handle.h" 14 #include "base/threading/thread_task_runner_handle.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "chrome/common/extensions/api/automation_api_constants.h" 16 #include "chrome/common/extensions/api/automation_api_constants.h"
17 #include "chrome/common/extensions/chrome_extension_messages.h" 17 #include "chrome/common/extensions/chrome_extension_messages.h"
18 #include "chrome/common/extensions/manifest_handlers/automation.h" 18 #include "chrome/common/extensions/manifest_handlers/automation.h"
19 #include "content/public/renderer/render_frame.h" 19 #include "content/public/renderer/render_frame.h"
20 #include "content/public/renderer/render_thread.h" 20 #include "content/public/renderer/render_thread.h"
21 #include "content/public/renderer/render_view.h" 21 #include "content/public/renderer/render_view.h"
22 #include "extensions/common/extension.h" 22 #include "extensions/common/extension.h"
23 #include "extensions/common/manifest.h" 23 #include "extensions/common/manifest.h"
24 #include "extensions/common/manifest_handlers/background_info.h" 24 #include "extensions/common/manifest_handlers/background_info.h"
25 #include "extensions/renderer/extension_bindings_system.h" 25 #include "extensions/renderer/extension_bindings_system.h"
26 #include "extensions/renderer/script_context.h" 26 #include "extensions/renderer/script_context.h"
27 #include "gin/converter.h"
27 #include "ipc/message_filter.h" 28 #include "ipc/message_filter.h"
28 #include "ui/accessibility/ax_enums.h" 29 #include "ui/accessibility/ax_enums.h"
29 #include "ui/accessibility/ax_node.h" 30 #include "ui/accessibility/ax_node.h"
30 #include "ui/gfx/geometry/rect_conversions.h" 31 #include "ui/gfx/geometry/rect_conversions.h"
31 32
32 namespace extensions { 33 namespace extensions {
33 34
34 namespace { 35 namespace {
35 36
36 void ThrowInvalidArgumentsException( 37 void ThrowInvalidArgumentsException(
37 AutomationInternalCustomBindings* automation_bindings) { 38 AutomationInternalCustomBindings* automation_bindings) {
38 v8::Isolate* isolate = automation_bindings->GetIsolate(); 39 v8::Isolate* isolate = automation_bindings->GetIsolate();
39 automation_bindings->GetIsolate()->ThrowException( 40 automation_bindings->GetIsolate()->ThrowException(
40 v8::String::NewFromUtf8( 41 v8::String::NewFromUtf8(
41 isolate, 42 isolate,
42 "Invalid arguments to AutomationInternalCustomBindings function", 43 "Invalid arguments to AutomationInternalCustomBindings function",
43 v8::NewStringType::kNormal) 44 v8::NewStringType::kNormal)
44 .ToLocalChecked()); 45 .ToLocalChecked());
45 46
46 LOG(FATAL) << "Invalid arguments to AutomationInternalCustomBindings function" 47 LOG(FATAL) << "Invalid arguments to AutomationInternalCustomBindings function"
47 << automation_bindings->context()->GetStackTraceAsString(); 48 << automation_bindings->context()->GetStackTraceAsString();
48 } 49 }
49 50
50 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate, const char* str) { 51 v8::Local<v8::String> CreateV8String(v8::Isolate* isolate,
51 return v8::String::NewFromUtf8(isolate, str, v8::String::kNormalString, 52 base::StringPiece str) {
52 strlen(str)); 53 return gin::StringToSymbol(isolate, str);
53 } 54 }
54 55
55 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate, 56 // Note: when building up an object to return from one of the
56 const std::string& str) { 57 // automation API bindings like a rect ({left: 0, top: 0, ...}) or
57 return v8::String::NewFromUtf8(isolate, str.c_str(), 58 // something like that, we should use this function instead of
58 v8::String::kNormalString, str.length()); 59 // v8::Object::Set, because a malicious extension author could use
60 // Object.defineProperty to override a setter and trigger all sorts of
61 // things to happen in the middle of one of our functions below.
62 //
63 // This is only safe when we're creating the object to return and
64 // we're setting properties on it before it's been exposed to
65 // untrusted scripts.
66 void SafeSetV8Property(v8::Isolate* isolate,
67 v8::Local<v8::Object> object,
68 base::StringPiece key,
69 v8::Local<v8::Value> value) {
70 v8::Maybe<bool> maybe = object->CreateDataProperty(
71 isolate->GetCurrentContext(), CreateV8String(isolate, key), value);
72
73 // There's no legit reason CreateDataProperty should fail.
74 CHECK(maybe.IsJust() && maybe.FromJust());
59 } 75 }
60 76
61 v8::Local<v8::Object> RectToV8Object(v8::Isolate* isolate, 77 v8::Local<v8::Object> RectToV8Object(v8::Isolate* isolate,
62 const gfx::Rect& rect) { 78 const gfx::Rect& rect) {
63 v8::Local<v8::Object> result(v8::Object::New(isolate)); 79 v8::Local<v8::Object> result(v8::Object::New(isolate));
64 result->Set(CreateV8String(isolate, "left"), 80 SafeSetV8Property(isolate, result, "left",
65 v8::Integer::New(isolate, rect.x())); 81 v8::Integer::New(isolate, rect.x()));
66 result->Set(CreateV8String(isolate, "top"), 82 SafeSetV8Property(isolate, result, "top",
67 v8::Integer::New(isolate, rect.y())); 83 v8::Integer::New(isolate, rect.y()));
68 result->Set(CreateV8String(isolate, "width"), 84 SafeSetV8Property(isolate, result, "width",
69 v8::Integer::New(isolate, rect.width())); 85 v8::Integer::New(isolate, rect.width()));
70 result->Set(CreateV8String(isolate, "height"), 86 SafeSetV8Property(isolate, result, "height",
71 v8::Integer::New(isolate, rect.height())); 87 v8::Integer::New(isolate, rect.height()));
72 return result; 88 return result;
73 } 89 }
74 90
75 // Compute the bounding box of a node, fixing nodes with empty bounds by 91 // Compute the bounding box of a node, fixing nodes with empty bounds by
76 // unioning the bounds of their children. 92 // unioning the bounds of their children.
77 static gfx::RectF ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) { 93 static gfx::RectF ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) {
78 gfx::RectF bounds = node->data().location; 94 gfx::RectF bounds = node->data().location;
79 if (bounds.width() > 0 && bounds.height() > 0) 95 if (bounds.width() > 0 && bounds.height() > 0)
80 return bounds; 96 return bounds;
81 97
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 if (!cache) 954 if (!cache)
939 return; 955 return;
940 956
941 TreeCache* focused_tree_cache = nullptr; 957 TreeCache* focused_tree_cache = nullptr;
942 ui::AXNode* focused_node = nullptr; 958 ui::AXNode* focused_node = nullptr;
943 if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node)) 959 if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node))
944 return; 960 return;
945 961
946 v8::Isolate* isolate = GetIsolate(); 962 v8::Isolate* isolate = GetIsolate();
947 v8::Local<v8::Object> result(v8::Object::New(isolate)); 963 v8::Local<v8::Object> result(v8::Object::New(isolate));
948 result->Set(CreateV8String(isolate, "treeId"), 964 SafeSetV8Property(isolate, result, "treeId",
949 v8::Integer::New(isolate, focused_tree_cache->tree_id)); 965 v8::Integer::New(isolate, focused_tree_cache->tree_id));
950 result->Set(CreateV8String(isolate, "nodeId"), 966 SafeSetV8Property(isolate, result, "nodeId",
951 v8::Integer::New(isolate, focused_node->id())); 967 v8::Integer::New(isolate, focused_node->id()));
952 args.GetReturnValue().Set(result); 968 args.GetReturnValue().Set(result);
953 } 969 }
954 970
955 void AutomationInternalCustomBindings::GetHtmlAttributes( 971 void AutomationInternalCustomBindings::GetHtmlAttributes(
956 const v8::FunctionCallbackInfo<v8::Value>& args) { 972 const v8::FunctionCallbackInfo<v8::Value>& args) {
957 v8::Isolate* isolate = GetIsolate(); 973 v8::Isolate* isolate = GetIsolate();
958 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) 974 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
959 ThrowInvalidArgumentsException(this); 975 ThrowInvalidArgumentsException(this);
960 976
961 int tree_id = args[0]->Int32Value(); 977 int tree_id = args[0]->Int32Value();
962 int node_id = args[1]->Int32Value(); 978 int node_id = args[1]->Int32Value();
963 979
964 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); 980 TreeCache* cache = GetTreeCacheFromTreeID(tree_id);
965 if (!cache) 981 if (!cache)
966 return; 982 return;
967 983
968 ui::AXNode* node = cache->tree.GetFromId(node_id); 984 ui::AXNode* node = cache->tree.GetFromId(node_id);
969 if (!node) 985 if (!node)
970 return; 986 return;
971 987
972 v8::Local<v8::Object> dst(v8::Object::New(isolate)); 988 v8::Local<v8::Object> dst(v8::Object::New(isolate));
973 base::StringPairs src = node->data().html_attributes; 989 base::StringPairs src = node->data().html_attributes;
974 for (size_t i = 0; i < src.size(); i++) { 990 for (size_t i = 0; i < src.size(); i++) {
975 std::string& key = src[i].first; 991 std::string& key = src[i].first;
976 std::string& value = src[i].second; 992 std::string& value = src[i].second;
977 dst->Set(CreateV8String(isolate, key), CreateV8String(isolate, value)); 993 SafeSetV8Property(isolate, dst, key, CreateV8String(isolate, value));
978 } 994 }
979 args.GetReturnValue().Set(dst); 995 args.GetReturnValue().Set(dst);
980 } 996 }
981 997
982 void AutomationInternalCustomBindings::GetState( 998 void AutomationInternalCustomBindings::GetState(
983 const v8::FunctionCallbackInfo<v8::Value>& args) { 999 const v8::FunctionCallbackInfo<v8::Value>& args) {
984 v8::Isolate* isolate = GetIsolate(); 1000 v8::Isolate* isolate = GetIsolate();
985 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) 1001 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
986 ThrowInvalidArgumentsException(this); 1002 ThrowInvalidArgumentsException(this);
987 1003
988 int tree_id = args[0]->Int32Value(); 1004 int tree_id = args[0]->Int32Value();
989 int node_id = args[1]->Int32Value(); 1005 int node_id = args[1]->Int32Value();
990 1006
991 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); 1007 TreeCache* cache = GetTreeCacheFromTreeID(tree_id);
992 if (!cache) 1008 if (!cache)
993 return; 1009 return;
994 1010
995 ui::AXNode* node = cache->tree.GetFromId(node_id); 1011 ui::AXNode* node = cache->tree.GetFromId(node_id);
996 if (!node) 1012 if (!node)
997 return; 1013 return;
998 1014
999 v8::Local<v8::Object> state(v8::Object::New(isolate)); 1015 v8::Local<v8::Object> state(v8::Object::New(isolate));
1000 uint32_t state_pos = 0, state_shifter = node->data().state; 1016 uint32_t state_pos = 0, state_shifter = node->data().state;
1001 while (state_shifter) { 1017 while (state_shifter) {
1002 if (state_shifter & 1) { 1018 if (state_shifter & 1) {
1003 std::string key = ToString(static_cast<ui::AXState>(state_pos)); 1019 std::string key = ToString(static_cast<ui::AXState>(state_pos));
1004 state->Set(CreateV8String(isolate, key), v8::Boolean::New(isolate, true)); 1020 SafeSetV8Property(isolate, state, key, v8::Boolean::New(isolate, true));
1005 } 1021 }
1006 state_shifter = state_shifter >> 1; 1022 state_shifter = state_shifter >> 1;
1007 state_pos++; 1023 state_pos++;
1008 } 1024 }
1009 1025
1010 TreeCache* top_cache = GetTreeCacheFromTreeID(0); 1026 TreeCache* top_cache = GetTreeCacheFromTreeID(0);
1011 if (!top_cache) 1027 if (!top_cache)
1012 top_cache = cache; 1028 top_cache = cache;
1013 TreeCache* focused_cache = nullptr; 1029 TreeCache* focused_cache = nullptr;
1014 ui::AXNode* focused_node = nullptr; 1030 ui::AXNode* focused_node = nullptr;
1015 if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) { 1031 if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) {
1016 if (focused_cache == cache && focused_node == node) { 1032 if (focused_cache == cache && focused_node == node) {
1017 state->Set(CreateV8String(isolate, "focused"), 1033 SafeSetV8Property(isolate, state, "focused",
1018 v8::Boolean::New(isolate, true)); 1034 v8::Boolean::New(isolate, true));
1019 } 1035 }
1020 } 1036 }
1021 if (cache->tree.data().focus_id == node->id()) { 1037 if (cache->tree.data().focus_id == node->id()) {
1022 state->Set(CreateV8String(isolate, "focused"), 1038 SafeSetV8Property(isolate, state, "focused",
1023 v8::Boolean::New(isolate, true)); 1039 v8::Boolean::New(isolate, true));
1024 } 1040 }
1025 1041
1026 args.GetReturnValue().Set(state); 1042 args.GetReturnValue().Set(state);
1027 } 1043 }
1028 1044
1029 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { 1045 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() {
1030 tree_change_observer_overall_filter_ = 0; 1046 tree_change_observer_overall_filter_ = 0;
1031 for (const auto& observer : tree_change_observers_) 1047 for (const auto& observer : tree_change_observers_)
1032 tree_change_observer_overall_filter_ |= 1 << observer.filter; 1048 tree_change_observer_overall_filter_ |= 1 << observer.filter;
1033 } 1049 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 for (auto id : ids) 1429 for (auto id : ids)
1414 nodes->AppendInteger(id); 1430 nodes->AppendInteger(id);
1415 args.Append(std::move(nodes)); 1431 args.Append(std::move(nodes));
1416 } 1432 }
1417 1433
1418 bindings_system_->DispatchEventInContext("automationInternal.onNodesRemoved", 1434 bindings_system_->DispatchEventInContext("automationInternal.onNodesRemoved",
1419 &args, nullptr, context()); 1435 &args, nullptr, context());
1420 } 1436 }
1421 1437
1422 } // namespace extensions 1438 } // namespace extensions
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698