microsoft / wil

Windows Implementation Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

registry enumeration has a bug with the key name field size and m_name_length getting out of sync.

ChrisGuzak opened this issue · comments

This shows a bug in the intermediate representations of the iterator. Note that passing by value works, by creating a copy and re-syncing the std::wstring size.

it seems when the size of the value name gets smaller is when this bug occurs.

it seems m_name_length is for the bstr case and I don't have much sympathy for code that needs the value name in that format. can we simplify this and get rid of m_name_length or not use a std::wstring in this case to avoid the duplication and incoherence it creates?

        // failing test. post this issue on github
        TEST_METHOD(VerifyRegistryEnumeratorWorksWithByRefParameter)
        {
            PCWSTR subKey = LR"(BugRepro)";
            auto extensionsIds = wil::reg::create_unique_key(HKEY_CURRENT_USER_LOCAL_SETTINGS, subKey, wil::reg::key_access::readwrite);
            wil::reg::set_value_string(extensionsIds.get(), L"{00021401-0000-0000-C000-000000000046}", L"");
            wil::reg::set_value_string(extensionsIds.get(), L"{66742402-F9B9-11D1-A202-0000F81FEDEE}", L"");
            wil::reg::set_value_string(extensionsIds.get(), L"Windows.Foundation.Uri", L"");
            wil::reg::set_value_string(extensionsIds.get(), L"Windows.Foundation.PropertyValue", L"");
            wil::reg::set_value_string(extensionsIds.get(), L"Wrong", L"{F8F24682-0E3B-4BE3-B6F5-1EC33AFE207D}");

            auto begin = wil::reg::value_iterator{ extensionsIds.get() };
            auto end = wil::reg::value_iterator{};

            std::for_each(begin, end, [&](auto nameAndType) // this works
            {
                cpp_unit::Logger::WriteMessage(nameAndType.name.c_str());
                auto size = wcslen(nameAndType.name.c_str());
                cpp_unit::Assert::IsTrue(size == nameAndType.name.size());
            });

            std::for_each(begin, end, [&](auto&& nameAndType) // this fails with the size assert below
            {
                cpp_unit::Logger::WriteMessage(nameAndType.name.c_str());
                auto size = wcslen(nameAndType.name.c_str());
                cpp_unit::Assert::IsTrue(size == nameAndType.name.size()); // failing
            });
        }