AvaloniaUI/Avalonia · error · ArgumentOutOfRangeException
bufferSize
Error message
bufferSize
What it means
CopyPixelsCore requires the destination buffer to be at least stride * sourceRect.Height bytes. The check is performed in 64-bit to avoid an integer overflow that would otherwise let an oversized blit run past the buffer end. A smaller buffer produces a buffer overrun, hence the guard.
Source
Thrown at src/Avalonia.Base/Media/Imaging/Bitmap.cs:241
/// <remarks>
/// <paramref name="sourceRowBytes"/> is signed and may be negative: a negative value means the
/// source rows are laid out bottom-up, with <paramref name="sourceAddress"/> pointing at the
/// first (top) row. The destination <paramref name="stride"/> must be positive and at least the
/// tightly-packed row size. The caller is responsible for validating <paramref name="sourceRect"/>
/// against the source bounds (e.g. via <see cref="ValidateSourceRect"/>).
/// </remarks>
internal static unsafe void CopyPixelsCore(PixelRect sourceRect, IntPtr sourceAddress, int sourceRowBytes,
PixelFormat sourceFormat, IntPtr buffer, int bufferSize, int stride)
{
int minStride = checked(((sourceRect.Width * sourceFormat.BitsPerPixel) + 7) / 8);
if (stride < minStride)
throw new ArgumentOutOfRangeException(nameof(stride));
// 64-bit to avoid overflowing the guard for very large strides/heights, which would
// otherwise let an oversized contiguous blit/loop run past the buffers.
var minBufferSize = (long)stride * sourceRect.Height;
if (minBufferSize > bufferSize)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
var offsetX = checked(((sourceRect.X * sourceFormat.BitsPerPixel) + 7) / 8);
// Fast-path: when the source and destination layouts are identical, tightly-packed and
// forward (no row padding, no X offset, positive stride), the whole region is contiguous in
// both buffers and can be copied with a single blit. This is meaningfully faster than the
// per-row loop (up to ~5x for small images, ~30% for large ones). Requiring stride == minStride
// also guarantees we don't read past the source's last row.
if (offsetX == 0 && sourceRowBytes == stride && stride == minStride)
{
Unsafe.CopyBlock(buffer.ToPointer(),
(sourceAddress + sourceRowBytes * sourceRect.Y).ToPointer(), (uint)minBufferSize);
return;
}
for (var y = 0; y < sourceRect.Height; y++)
{
var srcAddress = sourceAddress + sourceRowBytes * (sourceRect.Y + y) + offsetX;View on GitHub (pinned to 11c5427268)
Solutions
- Size the buffer from the exact parameters you will pass: int bufferSize = checked((int)((long)stride * sourceRect.Height));
- When pooling, round the rented size up to stride*Height and slice to that length.
- Recompute bufferSize whenever stride or sourceRect changes.
- Use checked arithmetic to surface overflow as an exception rather than a too-small buffer.
Example fix
// before byte[] buf = new byte[stride * (int)bmp.PixelSize.Height]; // wrong if sourceRect is taller bmp.CopyPixels(rect, buf, buf.Length, stride); // after long minBufferSize = (long)stride * rect.Height; byte[] buf = new byte[checked((int)minBufferSize)]; bmp.CopyPixels(rect, buf, buf.Length, stride);
Defensive patterns
Strategy: validation
Validate before calling
long minBufferSize = (long)stride * sourceRect.Height; int bufferSize = checked((int)minBufferSize); byte[] buffer = new byte[bufferSize]; bmp.CopyPixels(sourceRect, buffer, bufferSize, stride);
Prevention
- Size the destination buffer from the exact stride and rect you pass.
- Use checked arithmetic to surface overflow.
- When pooling, round the rented buffer up to stride*Height.
When it happens
Trigger: Allocating bufferSize from width*height without accounting for stride padding; passing a buffer sized for a different (smaller) sourceRect; using stride*Height with the wrong height; reusing a buffer pool entry sized for a previous, smaller image.
Common situations: Pooling image buffers without rounding up to the largest expected stride*Height; switching destination to a padded stride without enlarging the buffer; copying a tall crop into a buffer sized for the original (shorter) image.
Related errors
- stride
- sourceRect
- The parameter value cannot be greater than '{MaxFontEmSize}'
- Output span must be at least as long as input span
- stride
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/a57cb4c0b7e877f4.
Report an issue: GitHub.