{"record":{"id":"078e58cfb39abc94","repo":"stride3d/stride","slug":"should-be-a-multiple-of-4","errorCode":null,"errorMessage":"Should be a multiple of 4.","messagePattern":"Should be a multiple of 4\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Foundation/Graphics/StandardImageHelper.cs","lineNumber":131,"sourceCode":"\n    /// <summary>\n    ///   Copies a block of memory from a source buffer to a destination buffer,\n    ///   converting each 32-bit pixel from RGBA to BGRA format.\n    /// </summary>\n    /// <param name=\"dest\">A pointer to the destination buffer that will receive the converted BGRA pixel data.</param>\n    /// <param name=\"src\">A pointer to the source buffer containing the RGBA pixel data to copy and convert.</param>\n    /// <param name=\"sizeInBytesToCopy\">\n    ///   The number of bytes to copy and convert. Must be a multiple of 4, as each pixel is represented by 4 bytes.\n    /// </param>\n    /// <exception cref=\"ArgumentException\"><paramref name=\"sizeInBytesToCopy\"/> is not a multiple of 4.</exception>\n    /// <remarks>\n    ///   The conversion swaps the red and blue channels for each pixel, effectively transforming the format\n    ///   from RGBA to BGRA.\n    /// </remarks>\n    private static unsafe void CopyMemoryBGRA(IntPtr dest, IntPtr src, int sizeInBytesToCopy)\n    {\n        if ((sizeInBytesToCopy & 3) != 0)\n            throw new ArgumentException(\"Should be a multiple of 4.\", nameof(sizeInBytesToCopy));\n\n        var bufferSize = sizeInBytesToCopy / 4;\n        var srcPtr = (uint*) src;\n        var destPtr = (uint*) dest;\n        for (int i = 0; i < bufferSize; ++i)\n        {\n            var value = *srcPtr++;\n            // value: 0xAARRGGBB or in reverse 0xAABBGGRR\n            value = BinaryPrimitives.ReverseEndianness(value);\n            // value: 0xBBGGRRAA or in reverse 0xRRGGBBAA\n            value = BitOperations.RotateRight(value, 8);\n            // value: 0xAABBGGRR or in reverse 0xAARRGGBB\n            *destPtr++ = value;\n        }\n    }\n\n    /// <summary>\n    ///   Copies a block of memory from a source buffer to a destination buffer,","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Foundation/Graphics/StandardImageHelper.cs#L113-L149","documentation":"CopyMemoryBGRA performs the RGBA-to-BGRA channel swap by iterating the buffer as uint (4 bytes per pixel), so the byte count must be a multiple of 4. It validates sizeInBytesToCopy & 3 == 0 and throws ArgumentException otherwise, preventing a partial-pixel copy or out-of-bounds write.","triggerScenarios":"Invoking CopyMemoryBGRA(dest, src, sizeInBytesToCopy) with a size not divisible by 4 — e.g. copying a partial row of an odd-width 24bpp buffer, or passing BufferStride minus padding incorrectly.","commonSituations":"Copying cropped sub-regions whose width is not an exact number of pixels in 4-byte units; buffers from 3-byte-per-pixel formats; stride arithmetic that leaves trailing padding bytes out of the size.","solutions":["Round sizeInBytesToCopy to a multiple of 4 (only copy whole pixels).","Copy row by row with width*4 bytes per row instead of one big bulk copy.","Convert 3-byte formats to a 4-byte format before BGRA swapping."],"exampleFix":"// before\nCopyMemoryBGRA(dest, src, width * 3);\n// after\nCopyMemoryBGRA(dest, src, width * 4); // 4 bytes per pixel","handlingStrategy":"validation","validationCode":"if ((sizeInBytesToCopy & 3) != 0)\n    throw new ArgumentException(\"CopyMemoryBGRA requires size to be a multiple of 4\");","typeGuard":"bool IsWholePixelCount(int bytes) => (bytes & 3) == 0;","tryCatchPattern":"try { CopyMemoryBGRA(dest, src, size); }\ncatch (ArgumentException ex) when (ex.ParamName == \"sizeInBytesToCopy\") { CopyRowByRow(dest, src, size); }","preventionTips":["Compute copy sizes as width * 4 for 4-byte pixel formats, never from byte-based strides of other formats.","Copy row-by-row when dealing with sub-regions or padded strides.","Assert (stride & 3) == 0 on buffers entering BGRA conversion paths."],"tags":["graphics","memory-copy","alignment","pixel-format"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}