[native] Replace the bundled properties map with a linked list - #12551
Open
simonrozsival wants to merge 1 commit into
Open
[native] Replace the bundled properties map with a linked list#12551simonrozsival wants to merge 1 commit into
simonrozsival wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Copilot review overview
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
src/native/clr/runtime-base/android-system.cc — 💡 suggestion (performance/alloc churn) — add_system_property() always allocates a new value… |
What changed in this PR
This PR updates the CoreCLR host’s debug-only bundled system property storage to remove the last std::unordered_map usage (and its <unordered_map> dependency), aligning the implementation with MonoVM’s long-standing BundledProperty singly linked list approach. It also corrects a pre-existing debug-only lookup bug where the property name was returned instead of the value, which could cause buffer over-reads.
Changes:
- Replace
AndroidSystem::bundled_propertiesfromstd::unordered_map<std::string, std::string>to a malloc’dBundledPropertysingly linked list (DEBUG-only). - Add
AndroidSystem::find_bundled_property()helper for linear lookup in the linked list. - Fix debug-only property lookup to return the correct value pointer and length.
| File | Description |
|---|---|
| src/native/clr/runtime-base/android-system.cc | Implements linked-list storage and correct lookup of bundled properties in DEBUG builds. |
| src/native/clr/include/runtime-base/android-system.hh | Removes <unordered_map> and introduces the DEBUG-only BundledProperty definition + storage pointer. |
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 06:10
ae48813 to
c5ad8c6
Compare
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
2 times, most recently
from
August 28, 2026 07:54
5bcebb9 to
ecc2418
Compare
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 08:47
ecc2418 to
1f23c98
Compare
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 08:56
1f23c98 to
a3d78dc
Compare
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 09:51
a3d78dc to
a1bee56
Compare
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 10:29
a1bee56 to
d202466
Compare
`AndroidSystem::bundled_properties` was an
`std::unordered_map<std::string, std::string>`, which is the only user of
`<unordered_map>` in the CoreCLR host. The properties are read from the
environment override files at run time, so the set is not known at build time
and cannot be a static sorted array - but the map buys us nothing either: the
entries are added once at startup, looked up a handful of times and there are
only a few of them.
Use the same malloc'd singly linked list MonoVM has always used for this
(`BundledProperty`), with the name allocated together with the node and the
value allocated separately so that setting a property twice can replace it.
This also fixes a real bug. The lookup returned the map key rather than the
value:
value_len = prop_iter->second.length ();
return prop_iter->first.c_str ();
so every bundled property resolved to its own *name*, reported with the
*value's* length - which over-reads past the end of the name whenever the value
is longer than the name.
Release builds are unaffected, this code is `#if defined (DEBUG)` only. In a
Debug build of android-system.cc it removes the last reference to
`std::__next_prime()` (12 undefined libc++ symbols instead of 13) and shrinks
the object file from 83,400 to 77,984 bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0a35a0db-502d-48c0-8468-e73b5dd0ab2e
simonrozsival
force-pushed
the
dev/simonrozsival/clr-bundled-properties
branch
from
August 28, 2026 12:06
d202466 to
a0ae195
Compare
Base automatically changed from
dev/simonrozsival/clr-drop-chrono
to
dev/simonrozsival/clr-timing-free-list
August 28, 2026 12:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Part of the drop-libc++ work for CoreCLR.
AndroidSystem::bundled_propertieswas anstd::unordered_map<std::string, std::string>and the only user of<unordered_map>in the CoreCLR host.A sorted static array + binary search isn't an option here: bundled properties are read from the environment override files at run time, so the set isn't known at build time. But the map isn't buying us anything either — the entries are added once during startup, looked up a handful of times, and there are only a few of them.
So this uses the same malloc'd singly linked list that MonoVM has always used for exactly this purpose (
BundledProperty), keeping the two runtimes consistent:The name is allocated together with the node (one allocation covers both); the value is allocated separately so that setting the same property twice can replace it. Allocation failure aborts, as elsewhere in this stack.
This also fixes a real bug
The lookup returned the map key instead of the value:
So in Debug builds every bundled property resolved to its own name, reported with the value's length. When the value is longer than the name that's an over-read past the end of the name's buffer. This is pre-existing on
main, and falls out of the rewrite for free.Results
This code is
#if defined (DEBUG)only, so Release builds are completely unaffected — I verified the undefined-libc++-symbol list per object file is byte-for-byte identical before and after (58 both ways).The win is in Debug builds. Compiling
android-system.ccwith the real build flags plus-DDEBUG:The symbol that disappears is
std::__ndk1::__next_prime()— the bucket-count helper that isunordered_map's only out-of-line dependency.Testing
-DDEBUG, and I confirmed viallvm-nmthat the new code is genuinely being compiled (find_bundled_propertyandadd_system_propertyare present in the object) rather than silently skipped.