| 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 value->clear(); |
| 152 return false; |
| 153 } |
| 154 return true; |
| 142 } | 155 } |
| 143 | 156 |
| 144 // Decodes a value from a PReg file given as a uint8_t vector. | 157 // Decodes a value from a PReg file given as a uint8_t vector. |
| 145 bool DecodePRegValue(uint32_t type, | 158 bool DecodePRegValue(uint32_t type, |
| 146 const std::vector<uint8_t>& data, | 159 const std::vector<uint8_t>& data, |
| 147 std::unique_ptr<base::Value>* value) { | 160 std::unique_ptr<base::Value>* value) { |
| 161 std::string data_utf8; |
| 148 switch (type) { | 162 switch (type) { |
| 149 case REG_SZ: | 163 case REG_SZ: |
| 150 case REG_EXPAND_SZ: | 164 case REG_EXPAND_SZ: |
| 151 value->reset(new base::Value(DecodePRegStringValue(data))); | 165 if (!DecodePRegStringValue(data, &data_utf8)) |
| 166 return false; |
| 167 value->reset(new base::Value(data_utf8)); |
| 152 return true; | 168 return true; |
| 153 case REG_DWORD_LITTLE_ENDIAN: | 169 case REG_DWORD_LITTLE_ENDIAN: |
| 154 case REG_DWORD_BIG_ENDIAN: | 170 case REG_DWORD_BIG_ENDIAN: |
| 155 if (data.size() == sizeof(uint32_t)) { | 171 if (data.size() == sizeof(uint32_t)) { |
| 156 uint32_t val = *reinterpret_cast<const uint32_t*>(data.data()); | 172 uint32_t val = *reinterpret_cast<const uint32_t*>(data.data()); |
| 157 if (type == REG_DWORD_BIG_ENDIAN) | 173 if (type == REG_DWORD_BIG_ENDIAN) |
| 158 val = base::NetToHost32(val); | 174 val = base::NetToHost32(val); |
| 159 else | 175 else |
| 160 val = base::ByteSwapToLE32(val); | 176 val = base::ByteSwapToLE32(val); |
| 161 value->reset(new base::Value(static_cast<int>(val))); | 177 value->reset(new base::Value(static_cast<int>(val))); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 240 |
| 225 std::string value_name(base::UTF16ToUTF8(value)); | 241 std::string value_name(base::UTF16ToUTF8(value)); |
| 226 if (!base::StartsWith(value_name, kActionTriggerPrefix, | 242 if (!base::StartsWith(value_name, kActionTriggerPrefix, |
| 227 base::CompareCase::SENSITIVE)) { | 243 base::CompareCase::SENSITIVE)) { |
| 228 std::unique_ptr<base::Value> value; | 244 std::unique_ptr<base::Value> value; |
| 229 if (DecodePRegValue(type, data, &value)) | 245 if (DecodePRegValue(type, data, &value)) |
| 230 dict->SetValue(value_name, std::move(value)); | 246 dict->SetValue(value_name, std::move(value)); |
| 231 return; | 247 return; |
| 232 } | 248 } |
| 233 | 249 |
| 250 std::string data_utf8; |
| 234 std::string action_trigger(base::ToLowerASCII( | 251 std::string action_trigger(base::ToLowerASCII( |
| 235 value_name.substr(arraysize(kActionTriggerPrefix) - 1))); | 252 value_name.substr(arraysize(kActionTriggerPrefix) - 1))); |
| 236 if (action_trigger == kActionTriggerDeleteValues) { | 253 if (action_trigger == kActionTriggerDeleteValues) { |
| 237 for (const std::string& value : | 254 if (DecodePRegStringValue(data, &data_utf8)) { |
| 238 base::SplitString(DecodePRegStringValue(data), ";", | 255 for (const std::string& value : |
| 239 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) | 256 base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE, |
| 240 dict->RemoveValue(value); | 257 base::SPLIT_WANT_NONEMPTY)) |
| 258 dict->RemoveValue(value); |
| 259 } |
| 241 } else if (base::StartsWith(action_trigger, kActionTriggerDeleteKeys, | 260 } else if (base::StartsWith(action_trigger, kActionTriggerDeleteKeys, |
| 242 base::CompareCase::SENSITIVE)) { | 261 base::CompareCase::SENSITIVE)) { |
| 243 for (const std::string& key : | 262 if (DecodePRegStringValue(data, &data_utf8)) { |
| 244 base::SplitString(DecodePRegStringValue(data), ";", | 263 for (const std::string& key : |
| 245 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) | 264 base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE, |
| 246 dict->RemoveKey(key); | 265 base::SPLIT_WANT_NONEMPTY)) |
| 266 dict->RemoveKey(key); |
| 267 } |
| 247 } else if (base::StartsWith(action_trigger, kActionTriggerDel, | 268 } else if (base::StartsWith(action_trigger, kActionTriggerDel, |
| 248 base::CompareCase::SENSITIVE)) { | 269 base::CompareCase::SENSITIVE)) { |
| 249 dict->RemoveValue(value_name.substr(arraysize(kActionTriggerPrefix) - 1 + | 270 dict->RemoveValue(value_name.substr(arraysize(kActionTriggerPrefix) - 1 + |
| 250 arraysize(kActionTriggerDel) - 1)); | 271 arraysize(kActionTriggerDel) - 1)); |
| 251 } else if (base::StartsWith(action_trigger, kActionTriggerDelVals, | 272 } else if (base::StartsWith(action_trigger, kActionTriggerDelVals, |
| 252 base::CompareCase::SENSITIVE)) { | 273 base::CompareCase::SENSITIVE)) { |
| 253 // Delete all values. | 274 // Delete all values. |
| 254 dict->ClearValues(); | 275 dict->ClearValues(); |
| 255 } else if (base::StartsWith(action_trigger, kActionTriggerSecureKey, | 276 } else if (base::StartsWith(action_trigger, kActionTriggerSecureKey, |
| 256 base::CompareCase::SENSITIVE) || | 277 base::CompareCase::SENSITIVE) || |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 } | 397 } |
| 377 | 398 |
| 378 LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset " | 399 LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset " |
| 379 << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data); | 400 << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data); |
| 380 *status = POLICY_LOAD_STATUS_PARSE_ERROR; | 401 *status = POLICY_LOAD_STATUS_PARSE_ERROR; |
| 381 return false; | 402 return false; |
| 382 } | 403 } |
| 383 | 404 |
| 384 } // namespace preg_parser | 405 } // namespace preg_parser |
| 385 } // namespace policy | 406 } // namespace policy |
| OLD | NEW |