Skip to content

Commit

Permalink
Fix reading past end of array.
Browse files Browse the repository at this point in the history
Fix a bug in the `NonDelegatingGetIids()` implementation that could
cause reading past the end of the returned array.

`std::copy()` returns a pointer to the next element in the array after
the last element copied. The output argument `*array` was being assinged
to this pointer after the first copy, causing it to no longer point to
the beginning of the array. If the caller tries to access the full array
after this, it will read past the end of the array and will miss the
first elements of the array.

To fix, introduce a new temporary `_array` variable to pass the result
of the first copy as the starting point of the second copy. Also add a
test that failed before the fix and passes after the fix.
  • Loading branch information
dlech committed Jan 12, 2025
1 parent fd0e959 commit efc2f0f
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
4 changes: 2 additions & 2 deletions strings/base_implements.h
Original file line number Diff line number Diff line change
Expand Up @@ -1033,8 +1033,8 @@ namespace winrt::impl
{
return error_bad_alloc;
}
*array = std::copy(local_iids.second, local_iids.second + local_count, *array);
std::copy(inner_iids.cbegin(), inner_iids.cend(), *array);
auto _array = std::copy(local_iids.second, local_iids.second + local_count, *array);
std::copy(inner_iids.cbegin(), inner_iids.cend(), _array);
}
else
{
Expand Down
18 changes: 17 additions & 1 deletion test/old_tests/UnitTests/Composable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,20 @@ TEST_CASE("Composable conversions")
{
TestCalls(*make_self<Foo>());
TestCalls(*make_self<Bar>());
}
}

TEST_CASE("Composable get_interfaces")
{
struct Foo : Composable::BaseT<Foo, IStringable> {
hstring ToString() const { return L"Foo"; }
};

auto obj = make<Foo>();
auto iids = winrt::get_interfaces(obj);
// BaseOverrides IID gets repeated twice. There are only 4 unique interfaces.
REQUIRE(iids.size() >= 4);
REQUIRE(std::find(iids.begin(), iids.end(), guid_of<IBase>()) != iids.end());
REQUIRE(std::find(iids.begin(), iids.end(), guid_of<IBaseProtected>()) != iids.end());
REQUIRE(std::find(iids.begin(), iids.end(), guid_of<IBaseOverrides>()) != iids.end());
REQUIRE(std::find(iids.begin(), iids.end(), guid_of<IStringable>()) != iids.end());
}

0 comments on commit efc2f0f

Please sign in to comment.