From 067e0b6aa59910df33b4f449540539f076a38332 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\cray" <cray@hpa-win7-mtg1.basistech.net> Date: Tue, 22 Jan 2019 12:16:08 -0500 Subject: [PATCH] Updates From standup it was decided that we should return data as it is found in the registry. This means that data will be null terminated only if it was null termianted in the registry. --- rejistry++/src/RegistryByteBuffer.cpp | 92 ++++++++++++++------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/rejistry++/src/RegistryByteBuffer.cpp b/rejistry++/src/RegistryByteBuffer.cpp index 1322ea0e7..5e036383a 100644 --- a/rejistry++/src/RegistryByteBuffer.cpp +++ b/rejistry++/src/RegistryByteBuffer.cpp @@ -85,9 +85,13 @@ namespace Rejistry { return getASCIIString(0, _byteBuffer->limit()); } - /** - * Throws exception if offset or length is too large. - */ + /** + * Reads data from the registry and returns the data as a string + * as it is represented in the registry, including Null characters. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::string RegistryByteBuffer::getASCIIString(const uint32_t offset, const uint32_t length) const { if (length == 0) { return ""; @@ -102,60 +106,52 @@ namespace Rejistry { return getUTF16String(0, _byteBuffer->limit()); } + /** + * Reads data from the registry and returns a wstring of the data + * as it is represented in the registry, including Null characters. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::wstring RegistryByteBuffer::getUTF16String(const uint32_t offset, const uint32_t length) const { - if (length == 0) { - return L""; - } - - ByteBuffer::ByteArray &data = getData(offset, length); - // If the size of the array is not a multiple of 2 it is - // likely to not be UTF16 encoded. The most common case is that - // the string is simply missing a terminating null so we add it. - if (data.size() % 2 != 0) { - data.push_back('\0'); - } - - // Find UTF16 null terminator. - uint32_t nullPos = 0; - for (; nullPos < data.size(); nullPos += 2) { - if (data[nullPos] == '\0' && data[nullPos+1] == '\0') { - break; - } - } - - // empty string - if (nullPos == 0) { - return L""; - } + if (length == 0) { + return L""; + } - // UFT16 NULL char not found so add it - // Non-ascii registry key names seem to not be NULL terminated - // which leads to conversion errors in from_bytes() (CT-2917) - else if (nullPos == data.size()) { - data.push_back('\0'); + ByteBuffer::ByteArray &data = getData(offset, length); + // There are cases where an odd number of bytes are returned which + // leads to errors during conversion. See CT-2917 test12 for more details. + if (data.size() % 2 != 0) { data.push_back('\0'); } - std::wstring result; + // Empty value data (single UTF16 null char) + if (data.size() == 2 && data[0] == '\0' && data[1] == '\0') { + return L""; + } - try { - result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[nullPos])); - } - catch (std::exception&) - { - throw RegistryParseException("Error: Failed to convert string"); - } + std::wstring result; + try { + result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[data.size()])); + } + catch (std::exception&) + { + throw RegistryParseException("Error: Failed to convert string"); + } - return result; - } + return result; + } ByteBuffer::ByteArray RegistryByteBuffer::getData() const { return getData(0, _byteBuffer->limit()); } - /** - * Throws exception if offset and length are too large. - */ + /** + * Reads data from the registry based off of the given offset and length of data to read. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ ByteBuffer::ByteArray RegistryByteBuffer::getData(const uint32_t offset, const uint32_t length) const { uint32_t savedPosition = _byteBuffer->position(); _byteBuffer->position(offset); @@ -170,6 +166,12 @@ namespace Rejistry { return getStringList(0, _byteBuffer->limit()); } + /** + * Reads data from the registry based off of the given offset and length of data to read. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::vector<std::wstring> RegistryByteBuffer::getStringList(const uint32_t offset, const uint32_t length) const { std::vector<std::wstring> stringList; ByteBuffer::ByteArray data = getData(offset, length); -- GitLab