Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |