{"record":{"id":"856feab575f54c2f","repo":"stride3d/stride","slug":"pointer-to-dds-header-cannot-be-null","errorCode":null,"errorMessage":"Pointer to DDS header cannot be null","messagePattern":"Pointer to DDS header cannot be null","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Foundation/Graphics/DDSHelper.cs","lineNumber":299,"sourceCode":"\n        /// <summary>\n        /// Decodes DDS header including optional DX10 extended header\n        /// </summary>\n        /// <param name=\"headerPtr\">Pointer to the DDS header.</param>\n        /// <param name=\"size\">Size of the DDS content.</param>\n        /// <param name=\"flags\">Flags used for decoding the DDS header.</param>\n        /// <param name=\"description\">Output texture description.</param>\n        /// <param name=\"convFlags\">Output conversion flags.</param>\n        /// <exception cref=\"ArgumentException\">If the argument headerPtr is null</exception>\n        /// <exception cref=\"InvalidOperationException\">If the DDS header contains invalid datas.</exception>\n        /// <returns>True if the decoding is successfull, false if this is not a DDS header.</returns>\n        private static unsafe bool DecodeDDSHeader(IntPtr headerPtr, int size, DDSFlags flags, out ImageDescription description, out ConversionFlags convFlags)\n        {\n            description = new ImageDescription();\n            convFlags = ConversionFlags.None;\n\n            if (headerPtr == IntPtr.Zero)\n                throw new ArgumentException(\"Pointer to DDS header cannot be null\", \"headerPtr\");\n\n            if (size < (Unsafe.SizeOf<DDS.Header>() + sizeof (uint)))\n                return false;\n\n            // DDS files always start with the same magic number (\"DDS \")\n            if (*(uint*) (headerPtr) != DDS.MagicHeader)\n                return false;\n\n            var header = *(DDS.Header*) ((byte*) headerPtr + sizeof (int));\n\n            // Verify header to validate DDS file\n            if (header.Size != Unsafe.SizeOf<DDS.Header>() || header.PixelFormat.Size != Unsafe.SizeOf<DDS.DDSPixelFormat>())\n                return false;\n\n            // Setup MipLevels\n            description.MipLevels = header.MipMapCount;\n            if (description.MipLevels == 0)\n                description.MipLevels = 1;","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Foundation/Graphics/DDSHelper.cs#L281-L317","documentation":"DecodeDDSHeader validates the incoming pointer to a DDS header before parsing. A null/IntPtr.Zero pointer cannot contain a header, so it immediately throws ArgumentException naming the headerPtr parameter, mirroring DirectXTex's behavior.","triggerScenarios":"Calling DDS loading/decoding APIs (Image.Load / DDS decoding path) with IntPtr.Zero as the header pointer, typically from a failed buffer pin/allocation, passing an uninitialized pointer, or a null byte[] marshaled to pointer.","commonSituations":"P/Invoke or unsafe interop returning IntPtr.Zero on failure that is then passed to the DDS decoder, loading from a stream/buffer where the data pointer was never set, custom native integrations.","solutions":["Ensure the buffer containing DDS data is loaded and non-empty before decoding","Check any pointer-producing call (AllocGCHandle, Alloc, native alloc) for failure and handle IntPtr.Zero before calling","Fix the data-loading path so the DDS bytes are actually read into memory"],"exampleFix":"// before\nif (dataPtr == IntPtr.Zero) { /* unchecked */ }\nDecodeDDS(dataPtr, size, ...);\n// after\nif (dataPtr == IntPtr.Zero) throw new InvalidOperationException(\"DDS data not loaded\");\nDecodeDDS(dataPtr, size, ...);","handlingStrategy":"validation","validationCode":"if (headerPtr == IntPtr.Zero)\n    throw new InvalidOperationException(\"DDS data buffer was not loaded; cannot decode header\");\nif (size < 4 + sizeof(DDS.Header))\n    throw new InvalidOperationException(\"DDS buffer too small to contain a header\");","typeGuard":null,"tryCatchPattern":"try { ok = DecodeDDSHeader(ptr, size, flags, out desc, out conv); } catch (ArgumentException ex) when (ex.ParamName == \"headerPtr\") { // fix data loading before retry\n    throw new InvalidOperationException(\"DDS source pointer was null; load the file bytes first\", ex); }","preventionTips":["Always load DDS bytes into memory before decoding","Check pointer-returning allocation APIs for IntPtr.Zero","Assert non-null pointers near the interop boundary","Wrap native decode calls behind a managed loader that validates inputs"],"tags":["dds","textures","native-interop","null-pointer"],"backgroundTag":"null-argument","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"}