Skip to content

Ascii and Latin1 APIs can return wrong results for misaligned buffers #84877

Closed as not planned

Description

@MihaZupan
char* pBuffer = stackalloc char[17];
Span<char> misalignedSpan = new((char*)((byte*)pBuffer + 1), 16);
misalignedSpan.Fill('a');

if (!Ascii.IsValid(misalignedSpan)) Console.WriteLine("Oh no");

Ascii.IsValid pins the input and works with pointers internally. GetIndexOfFirstNonAsciiChar_Intrinsified will attempt to 16-byte align the input pointer to make use of aligned reads, but in doing so it ends up working with the "corrupted" data if the input wasn't 2-byte aligned initially.

pBuffer = (char*)(((nuint)pBuffer + SizeOfVector128InBytes) & ~(nuint)(SizeOfVector128InBytes - 1));

As a result it may end up returning the wrong result (both false positives and false negatives).

Latin1Utility also likely shares the same issue.

It's safe to assume that related operations on Encoding that make use of these helpers are likewise affected.

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 15, 2023
  2. added this to the 8.0.0 milestone on Apr 15, 2023
  3. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 15, 2023
  4. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 15, 2023
  5. tannergooding commented on Apr 17, 2023

    @tannergooding
    Member

    CC. @GrabYourPitchforks, this has been around for about 4 years since dotnet/coreclr#22516

    While the JIT expects that any T, ref T, or T* is "naturally aligned" and it expects you to use the unaligned. prefix (such as via Unsafe.ReadUnaligned) to access unaligned data; correctly detecting and handling data that is misaligned isn't difficult and won't noticeably hurt the common path. -- We should just need to check that address % 2 == 0 prior to trying to align the data.

  6. thatbakamono commented on Apr 18, 2023

    @thatbakamono

    I'd like to take care of this, could it be assigned to me?

  7. thatbakamono commented on Apr 29, 2023

    @thatbakamono

    The issue is actually not reproducible anymore with the provided example, I noticed after rebasing that Ascii.IsValid got reimplemented in #84881 without using the affected methods. All other APIs relying on GetIndexOfFirstNonXYZChar or GetIndexOfFirstNonXYZByte (where XYZ is either Ascii or Latin1) should be still affected.

  8. removed their assignment
    on May 11, 2023
  9. thatbakamono commented on May 11, 2023

    @thatbakamono

    Sorry for stalling the issue, I thought I'd be able to resolve it pretty quickly but a few unforeseen complications occurred and I don't think I'll be able to finish working on the fix any time soon. Thanks for the opportunity though, I learned quite a bit about the workflow and it'll allow me to make contributions more easily in the future.

  10. modified the milestones: 8.0.0, 9.0.0 on Oct 24, 2023
  11. GrabYourPitchforks commented on May 20, 2024

    @GrabYourPitchforks
    Member

    Looks like a dupe of #44497, which was resolved by-design. From that issue: in general, pointers are assumed to be properly aligned for the target data type, except in very specific circumstances where the API is expressly documented as supporting unaligned accesses.

  12. stephentoub commented on Jul 23, 2024

    @stephentoub
    Member

    Closing as duplicate and by-design per above.

  13. locked and limited conversation to collaborators on Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions