Skip to content

[release/11.0] Fix negative tmp-buffer size in vxsort align_vectorized - #135229

Merged
JulieLeeMSFT merged 1 commit into
release/11.0from
backport/pr-134881-to-release/11.0
Oct 6, 2026
Merged

JulieLeeMSFT merged 1 commit into
release/11.0from
backport/pr-134881-to-release/11.0

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Backport of #134881 to release/11.0

/cc @janvorli

Customer Impact

Server/Workstation GC background threads can crash with an access violation inside coreclr!memcpy, called from vxsort code during mark_phase/plan_phase sorting of the GC mark list.
The issue was first reported in May 2023, but we were never able to reproduce it.
Now a customer started to hit this issue on a regular basis in Azure App Service powering a multi-tenant SaaS solution. It resulted in SLA violations impacting the customer.

The culprit is a bug in the vxsort that has been in vxsort code ever since it was implemented in .NET Core 6

Regression

Testing

coreclr tests executed with server GC with GC stress C

Risk

Low, the change is local to boundary-lane classification in vxsort and preserves the existing sorting and buffer-management logic. It forces out-of-range lanes onto the side from which they are subsequently trimmed, preventing invalid copy sizes and contamination of the sorted output

## Issue
Server/Workstation GC background threads can crash with an access
violation (read) inside coreclr!memcpy, called from
vxsort<T,M,Unroll,Shift>::vectorized_partition, itself called from
do_vxsort during mark_phase/plan_phase sorting of the GC mark list. This
reproduces the crash originally reported in #86548 ("The
size calculated to be negative and cause Access Violation when doing
vxsort vectorized_partition"), which was closed without a fix in 2023
due to lack of a reliable repro. Analysis of a production Windows crash
dump (Second Chance Exception c0000005, AMD EPYC/Zen4 AVX-512)
root-caused the same failure independently and pinpointed the exact
algorithmic defect below.

## Root cause
In vxsort::align_vectorized(), when the left read pointer isn't
vector-aligned, the code pre-aligns by reading a full vector starting
before `left`. The low `L = -leftAlign` lanes of that vector are "junk"
elements that lie before the current [left, right] partition range
(already settled by an ancestor partition step), while the remaining
lanes are real elements of the current range. Both junk and real lanes
are compared against the current pivot and compacted together (via
compress-store or an order-preserving permute), so junk elements can
land on either side of the pivot - they are not guaranteed to all be <=
pivot.

The code advanced `tmpLeft` by the true, data-dependent count of <=pivot
lanes (`ltPopCountLeftPart`), but advanced `tmpStartLeft` - the base
pointer later used to size the copy-back region (`leftTmpSize = tmpLeft
- tmpStartLeft`) - by the *constant* `L`, implicitly assuming all L junk
lanes are <=pivot. When fewer than L junk lanes are actually <=pivot,
tmpStartLeft overshoots tmpLeft, producing a negative leftTmpSize. That
negative value, reinterpreted as an unsigned byte count in the
subsequent memcpy, causes a massive out-of-bounds read and the access
violation.

The formula was validated against both the original #86548 report (L=7,
ltMask=0x3f -> ltPopCountLeftPart=2 -> deficit of -5 elements = -20
bytes, exactly matching the reported value) and against the investigated
crash dump (1-element/4-byte deficit reproduced from register/stack
state captured in the dump).

The right-side counterpart (`tmpStartRight -= rightAlign & rai`) has the
same class of defect for junk elements read beyond `right`. It was
partially papered over by `rtPopCountRightPart = max(mask_popcount(
rtMask), rightAlign)`, which avoids the crash but can instead leave an
uninitialized "hole" in the tmp buffer that gets silently copied back
into the array as if it were valid sorted data.

## Fix
Replace the constant junk-lane skip on both sides with the exact,
data-dependent count of junk lanes that landed on the "keep" side of the
pivot, computed via a popcount masked to just the junk-lane bits (low L
bits for the left side, high `rightAlign` bits for the right side). This
removes the incorrect assumption entirely instead of papering over its
symptoms, and makes the previous `max()` band-aid on the right side
unnecessary (removed).

Validated by a full CoreCLR Debug x64 native build (build-runtime.cmd),
confirming the change compiles cleanly across the WKS/SVR GC, gcsample,
and NativeAOT runtime consumers, for both AVX2 and AVX-512 machine
traits and both int32/int64 element types.

Fixes #86548

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b029aa4e-2a19-4582-b9e5-4918cb4c3095
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @anicka-net, @dotnet/gc
See info in area-owners.md if you want to be subscribed.

@janvorli
janvorli requested a review from kkokosa October 6, 2026 13:38
@janvorli janvorli self-assigned this Oct 6, 2026
@janvorli janvorli added the Servicing-consider Issue for next servicing release review label Oct 6, 2026
@janvorli janvorli modified the milestones: 10.0.x, 11.0.0 Oct 6, 2026
@JulieLeeMSFT JulieLeeMSFT added Servicing-approved Approved for servicing release and removed Servicing-consider Issue for next servicing release review labels Oct 6, 2026
@JulieLeeMSFT

Copy link
Copy Markdown
Member

/ba-g known issues.

@JulieLeeMSFT
JulieLeeMSFT merged commit ffee866 into release/11.0 Oct 6, 2026
121 of 125 checks passed
@JulieLeeMSFT
JulieLeeMSFT deleted the backport/pr-134881-to-release/11.0 branch October 6, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-GC-coreclr Servicing-approved Approved for servicing release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants