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

Side by Side Diff: components/policy/core/common/preg_parser.cc

Issue 2852393002: Fix fuzzer crash for preg_parser (Closed)
Patch Set: 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
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "components/policy/core/common/preg_parser.h" 5 #include "components/policy/core/common/preg_parser.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 bool ReadFieldString(const uint8_t** cursor, 121 bool ReadFieldString(const uint8_t** cursor,
122 const uint8_t* end, 122 const uint8_t* end,
123 base::string16* str) { 123 base::string16* str) {
124 int current = -1; 124 int current = -1;
125 while ((current = NextChar(cursor, end)) > 0x0000) 125 while ((current = NextChar(cursor, end)) > 0x0000)
126 *str += current; 126 *str += current;
127 127
128 return current == L'\0'; 128 return current == L'\0';
129 } 129 }
130 130
131 std::string DecodePRegStringValue(const std::vector<uint8_t>& data) { 131 // Converts the UTF16 |data| to an UTF8 string |value|. Returns false if the
132 // resulting UTF8 string contains invalid characters.
133 bool DecodePRegStringValue(const std::vector<uint8_t>& data,
134 std::string* value) {
132 size_t len = data.size() / sizeof(base::char16); 135 size_t len = data.size() / sizeof(base::char16);
133 if (len <= 0) 136 if (len <= 0) {
134 return std::string(); 137 value->clear();
138 return true;
139 }
135 140
136 const base::char16* chars = 141 const base::char16* chars =
137 reinterpret_cast<const base::char16*>(data.data()); 142 reinterpret_cast<const base::char16*>(data.data());
138 base::string16 result; 143 base::string16 utf16_str;
139 std::transform(chars, chars + len - 1, std::back_inserter(result), 144 std::transform(chars, chars + len - 1, std::back_inserter(utf16_str),
140 std::ptr_fun(base::ByteSwapToLE16)); 145 std::ptr_fun(base::ByteSwapToLE16));
141 return base::UTF16ToUTF8(result); 146 // Note: UTF16ToUTF8() only checks whether all chars are valid code points,
147 // but not whether they're valid characters. IsStringUTF8(), however, does.
148 *value = base::UTF16ToUTF8(utf16_str);
149 if (!base::IsStringUTF8(*value)) {
150 LOG(ERROR) << "String '" << *value << "' is not a valid UTF8 string";
151 return false;
Thiemo Nagel 2017/05/02 15:48:31 Optional nit: Maybe clear |*value| as part of the
ljusten (tachyonic) 2017/05/02 15:58:32 Done.
152 }
153 return true;
142 } 154 }
143 155
144 // Decodes a value from a PReg file given as a uint8_t vector. 156 // Decodes a value from a PReg file given as a uint8_t vector.
145 bool DecodePRegValue(uint32_t type, 157 bool DecodePRegValue(uint32_t type,
146 const std::vector<uint8_t>& data, 158 const std::vector<uint8_t>& data,
147 std::unique_ptr<base::Value>* value) { 159 std::unique_ptr<base::Value>* value) {
160 std::string data_utf8;
148 switch (type) { 161 switch (type) {
149 case REG_SZ: 162 case REG_SZ:
150 case REG_EXPAND_SZ: 163 case REG_EXPAND_SZ:
151 value->reset(new base::Value(DecodePRegStringValue(data))); 164 if (!DecodePRegStringValue(data, &data_utf8))
165 return false;
166 value->reset(new base::Value(data_utf8));
152 return true; 167 return true;
153 case REG_DWORD_LITTLE_ENDIAN: 168 case REG_DWORD_LITTLE_ENDIAN:
154 case REG_DWORD_BIG_ENDIAN: 169 case REG_DWORD_BIG_ENDIAN:
155 if (data.size() == sizeof(uint32_t)) { 170 if (data.size() == sizeof(uint32_t)) {
156 uint32_t val = *reinterpret_cast<const uint32_t*>(data.data()); 171 uint32_t val = *reinterpret_cast<const uint32_t*>(data.data());
157 if (type == REG_DWORD_BIG_ENDIAN) 172 if (type == REG_DWORD_BIG_ENDIAN)
158 val = base::NetToHost32(val); 173 val = base::NetToHost32(val);
159 else 174 else
160 val = base::ByteSwapToLE32(val); 175 val = base::ByteSwapToLE32(val);
161 value->reset(new base::Value(static_cast<int>(val))); 176 value->reset(new base::Value(static_cast<int>(val)));
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 239
225 std::string value_name(base::UTF16ToUTF8(value)); 240 std::string value_name(base::UTF16ToUTF8(value));
226 if (!base::StartsWith(value_name, kActionTriggerPrefix, 241 if (!base::StartsWith(value_name, kActionTriggerPrefix,
227 base::CompareCase::SENSITIVE)) { 242 base::CompareCase::SENSITIVE)) {
228 std::unique_ptr<base::Value> value; 243 std::unique_ptr<base::Value> value;
229 if (DecodePRegValue(type, data, &value)) 244 if (DecodePRegValue(type, data, &value))
230 dict->SetValue(value_name, std::move(value)); 245 dict->SetValue(value_name, std::move(value));
231 return; 246 return;
232 } 247 }
233 248
249 std::string data_utf8;
234 std::string action_trigger(base::ToLowerASCII( 250 std::string action_trigger(base::ToLowerASCII(
235 value_name.substr(arraysize(kActionTriggerPrefix) - 1))); 251 value_name.substr(arraysize(kActionTriggerPrefix) - 1)));
236 if (action_trigger == kActionTriggerDeleteValues) { 252 if (action_trigger == kActionTriggerDeleteValues) {
237 for (const std::string& value : 253 if (DecodePRegStringValue(data, &data_utf8)) {
238 base::SplitString(DecodePRegStringValue(data), ";", 254 for (const std::string& value :
239 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) 255 base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE,
240 dict->RemoveValue(value); 256 base::SPLIT_WANT_NONEMPTY))
257 dict->RemoveValue(value);
258 }
241 } else if (base::StartsWith(action_trigger, kActionTriggerDeleteKeys, 259 } else if (base::StartsWith(action_trigger, kActionTriggerDeleteKeys,
242 base::CompareCase::SENSITIVE)) { 260 base::CompareCase::SENSITIVE)) {
243 for (const std::string& key : 261 if (DecodePRegStringValue(data, &data_utf8)) {
244 base::SplitString(DecodePRegStringValue(data), ";", 262 for (const std::string& key :
245 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) 263 base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE,
246 dict->RemoveKey(key); 264 base::SPLIT_WANT_NONEMPTY))
265 dict->RemoveKey(key);
266 }
247 } else if (base::StartsWith(action_trigger, kActionTriggerDel, 267 } else if (base::StartsWith(action_trigger, kActionTriggerDel,
248 base::CompareCase::SENSITIVE)) { 268 base::CompareCase::SENSITIVE)) {
249 dict->RemoveValue(value_name.substr(arraysize(kActionTriggerPrefix) - 1 + 269 dict->RemoveValue(value_name.substr(arraysize(kActionTriggerPrefix) - 1 +
250 arraysize(kActionTriggerDel) - 1)); 270 arraysize(kActionTriggerDel) - 1));
251 } else if (base::StartsWith(action_trigger, kActionTriggerDelVals, 271 } else if (base::StartsWith(action_trigger, kActionTriggerDelVals,
252 base::CompareCase::SENSITIVE)) { 272 base::CompareCase::SENSITIVE)) {
253 // Delete all values. 273 // Delete all values.
254 dict->ClearValues(); 274 dict->ClearValues();
255 } else if (base::StartsWith(action_trigger, kActionTriggerSecureKey, 275 } else if (base::StartsWith(action_trigger, kActionTriggerSecureKey,
256 base::CompareCase::SENSITIVE) || 276 base::CompareCase::SENSITIVE) ||
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 396 }
377 397
378 LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset " 398 LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset "
379 << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data); 399 << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data);
380 *status = POLICY_LOAD_STATUS_PARSE_ERROR; 400 *status = POLICY_LOAD_STATUS_PARSE_ERROR;
381 return false; 401 return false;
382 } 402 }
383 403
384 } // namespace preg_parser 404 } // namespace preg_parser
385 } // namespace policy 405 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/test/data/policy/registry.pol ('k') | components/policy/core/common/preg_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698