-
Notifications
You must be signed in to change notification settings - Fork 507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[xcode14.1] [Foundation] Fix random memory access / memory corruption in NSFastEnumerator. Fixes #xamarin/maccore@1347. #16941
Conversation
…umerator. Fixes #xamarin/maccore@1347. The NSFastEnumerator protocol in Objective-C works like this: 1. A selector is called on the collection in question, where we give the native method a pointer to a state structure. Upon return, the state structure will have two important pointers: one to a C array with the pointers to enumerate, and another pointer that points to a value determining whether the collection was modified since enumeration started. 2. In the original managed implementation, we'd store the state (a struct) as an instance field of NSFastEnumerator. This works fine... most of the time. Unfortunately most of the time isn't good enough, because this may happen: a. The native iterator function might store a pointer into the state structure itself as the pointer to check for a modified collection. b. The GC runs, and moves memory around. Now suddenly the pointer we have to read to check if the collection was modified is pointing to the previous location of the state structure, which could be anything or anywhere, and the app subsequently tries to summon Murphy from his pantheon in the sky (admittedly with limited success). The fix is to use native memory (which the GC won't move around) to store the enumeration state. Also optimize memory usage a little bit by allocating one big blob for both the state and the array of pointers we pass to the native iterator method. Fixes xamarin/maccore#1347. Fixes xamarin/maccore#2606.
✅ API diff for current PR / commitLegacy Xamarin (No breaking changes)
NET (empty diffs)
❗ API diff vs stable (Breaking changes)Legacy Xamarin (:heavy_exclamation_mark: Breaking changes :heavy_exclamation_mark:).NET (:heavy_exclamation_mark: Breaking changes :heavy_exclamation_mark:)✅ Generator diffGenerator diff is empty Pipeline on Agent |
❌ [PR Build] Tests on macOS M1 - Mac Big Sur (11.5) failed ❌Failed tests are:
Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build] Test results 🚀Test results✅ All tests passed on VSTS: simulator tests. 🎉 All 223 tests passed 🎉 Tests counts✅ bcl: All 69 tests passed. Html Report (VSDrops) Download Pipeline on Agent |
The NSFastEnumerator protocol in Objective-C works like this:
native method a pointer to a state structure. Upon return, the state
structure will have two important pointers: one to a C array with the
pointers to enumerate, and another pointer that points to a value
determining whether the collection was modified since enumeration started.
an instance field of NSFastEnumerator.
This works fine... most of the time. Unfortunately most of the time isn't good
enough, because this may happen:
a. The native iterator function might store a pointer into the state structure
itself as the pointer to check for a modified collection.
b. The GC runs, and moves memory around.
Now suddenly the pointer we have to read to check if the collection was
modified is pointing to the previous location of the state structure, which
could be anything or anywhere, and the app subsequently tries to summon Murphy
from his pantheon in the sky (admittedly with limited success).
The fix is to use native memory (which the GC won't move around) to store the
enumeration state.
Also optimize memory usage a little bit by allocating one big blob for both
the state and the array of pointers we pass to the native iterator method.
Fixes https://github.com/xamarin/maccore/issues/1347.
Fixes https://github.com/xamarin/maccore/issues/2606.
Backport of #16920