Skip to content

[Foundation] Fix NSCoder.Encode(byte[], offset, count, key) to honor offset/count#26015

Open
rolfbjarne wants to merge 2 commits into
mainfrom
dev/rolf/miniature-chainsaw
Open

[Foundation] Fix NSCoder.Encode(byte[], offset, count, key) to honor offset/count#26015
rolfbjarne wants to merge 2 commits into
mainfrom
dev/rolf/miniature-chainsaw

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

Why

NSCoder.Encode (byte[] buffer, int offset, int count, string key) validated its offset and count arguments but then ignored them. It pinned the start of the buffer and passed buffer.Length to EncodeBlock, so it always encoded the entire array regardless of the requested [offset, offset+count) segment. This is a latent correctness bug: callers asking to encode a slice silently got the whole buffer.

The bug was found during the issue #3590 Span-API survey. A future ReadOnlySpan<byte> overload would fix it implicitly, but the existing overload deserves its own targeted fix and test now.

What

  • src/Foundation/NSCoder.cs: pin the buffer and call EncodeBlock ((IntPtr) (p + offset), count, key), matching the pointer idiom used by the sibling Encode overloads.
  • tests/monotouch-test/Foundation/CoderTest.cs: the existing test already encoded {3,14,15} with offset 2, count 1 under key "buffer2", but its assertion checked that the whole buffer round-tripped, i.e. it asserted the buggy behavior. Updated it to assert the decoded segment is exactly the [offset, count) slice (buf.Length == 1 and buf[0] == buffer[2]). This fails with the old code and passes with the fix.

Testing

  • Full clean build succeeded (0 warnings, 0 errors).
  • Confirmed the fix is compiled into the built Microsoft.iOS.dll by disassembling it: the IL now computes p + offset and passes count to EncodeBlock.
  • The monotouch-test suite could not be executed in this environment because the required Xcode (SDK 26.5) is not installed, so the native test-libraries do not compile. CI will run the test.

🤖 Pull request created by Copilot

…offset/count.

The offset/count overload validated its arguments but ignored them: it
pinned the start of the buffer and passed buffer.Length to EncodeBlock,
so it always encoded the entire array instead of the requested
[offset, offset+count) segment.

Pin the buffer and pass (IntPtr)(p + offset) and count instead, matching
the behavior of the sibling Encode overloads. Also fix the existing
CoderTest to assert the encoded segment is exactly the [offset, count)
slice (the previous assertion encoded the buggy whole-buffer behavior).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a correctness bug in the Foundation NSCoder.Encode (byte[], offset, count, key) overload where offset/count were validated but not actually honored, and updates the corresponding regression test to assert slice-based behavior instead of the previous (buggy) full-buffer round-trip.

Changes:

  • Update NSCoder.Encode (byte[], offset, count, key) to pass p + offset and count to EncodeBlock.
  • Adjust CoderTest.EncodeDecodeTest to assert that decoding "buffer2" returns only the requested segment.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Foundation/NSCoder.cs Fixes encoding logic to honor offset/count when encoding byte segments.
tests/monotouch-test/Foundation/CoderTest.cs Updates assertions so the test validates slice encoding rather than full-buffer encoding.

Comment thread tests/monotouch-test/Foundation/CoderTest.cs Outdated
Address review feedback: with offset=2,count=1 the count happened to
equal buffer.Length - offset, so an implementation that encoded
buffer.Length - offset bytes (instead of count) would still pass.
Using offset=1,count=1 keeps count independent of buffer.Length - offset
and offset non-zero, so offset and count are both exercised.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne marked this pull request as ready for review July 10, 2026 09:43
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 68b6437d8cb94bf4f7828300033229cba307af84 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne enabled auto-merge (squash) July 10, 2026 12:31
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #68b6437] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 1 tests failed, 198 tests passed.

Failures

❌ monotouch tests (MacCatalyst) [attempt 2]

1 tests failed, 16 tests passed.

Failed tests

  • monotouch-test/Mac Catalyst/Debug: HarnessException (Harness exception for 'monotouch-test': System.Exception: Unable to evaluate the property OutputPath in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/bin/Debug/tmp-test-dir/monotouch-test74/monotouch-test.csproj, build failed with exit code 139. Timed out: False
    at Xharness.AppBundleLocator.GetPropertyByMSBuildEvaluationAsync(XmlDocument csproj, String projectPath, String evaluateProperty, String dependsOnTargets, Dictionary`2 properties) in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/AppBundleLocator.cs:line 100
    at Xharness.AppBundleLocator.LocateAppBundle(XmlDocument projectFile, String projectFilePath, TestTarget target, String buildConfiguration) in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/AppBundleLocator.cs:line 48
    at Xharness.Jenkins.TestTasks.MacExecuteTask.RunTestAsync() in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/Jenkins/TestTasks/MacExecuteTask.cs:line 52
    at Xharness.Jenkins.TestTasks.RunTest.ExecuteAsync() in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/Jenkins/TestTasks/RunTest.cs:line 113
    at Xharness.Jenkins.TestTasks.TestTask.RunInternalAsync() in /Users/cloudtest/vss/_work/1/s/macios/tests/xharness/Jenkins/TestTasks/TestTask.cs:line 234)

Html Report (VSDrops) Download

Successes

✅ assembly-processing: All 1 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 18 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 68b6437d8cb94bf4f7828300033229cba307af84 [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants