{"record":{"id":"db57cbde866da744","repo":"QL-Win/QuickLook","slug":"1-bpp-mask-underrun-parsing-icns-file","errorCode":null,"errorMessage":"1 BPP mask underrun parsing ICNS file","messagePattern":"1 BPP mask underrun parsing ICNS file","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"QuickLook.Plugin/QuickLook.Plugin.ImageViewer/AnimatedImage/Providers/IcnsProvider.cs","lineNumber":305,"sourceCode":"                             (0xffu & imageData[4 * (y * imageType.Width + x) + 3]));\n\n                SetPixel(image, x, y, argb);\n            }\n    }\n\n    private static void Apply1BPPMask(byte[] maskData, BitmapData image)\n    {\n        int position;\n        int bitsLeft = 0;\n        int value = 0;\n\n        // 1 bit icon types have image data followed by mask data in the same entry\n        int totalBytes = (image.Width * image.Height + 7) / 8;\n\n        if (maskData.Length >= 2 * totalBytes)\n            position = totalBytes;\n        else\n            throw new ArgumentException(\"1 BPP mask underrun parsing ICNS file\");\n\n        for (int y = 0; y < image.Height; y++)\n            for (int x = 0; x < image.Width; x++)\n            {\n                if (bitsLeft == 0)\n                {\n                    value = 0xff & maskData[position++];\n                    bitsLeft = 8;\n                }\n\n                uint alpha;\n                alpha = (value & 0x80u) != 0 ? 0xffu : 0x00u;\n                value <<= 1;\n                bitsLeft--;\n\n                SetPixel(image, x, y, (alpha << 24) | (0xffffffu & GetPixel(image, x, y)));\n            }\n    }","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/QL-Win/QuickLook/blob/cb5d9c429c81d9796fac469da2a68efb5626946d/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/AnimatedImage/Providers/IcnsProvider.cs#L287-L323","documentation":"Thrown by IcnsProvider.Apply1BPPMask when the mask data buffer is shorter than expected. For 1-bit-per-pixel ICNS icons the entry packs image data then mask data contiguously; the method computes totalBytes = (W*H+7)/8 and requires maskData.Length >= 2*totalBytes so it can start the mask at offset totalBytes. If the buffer is shorter, the mask underruns and parsing is aborted with ArgumentException.","triggerScenarios":"For a 1BPP ICNS type, the element's data array has fewer than 2*ceil(W*H/8) bytes, so the mask half is missing or partial. Occurs with hand-edited, truncated, or non-spec ICNS files where the icon entry was not fully written.","commonSituations":"An ICNS exported by a tool that omits the mask channel for monochrome icons; a file truncated mid-entry; an icon type misidentified as 1BPP due to a wrong type-code mapping.","solutions":["Re-export the ICNS with a spec-compliant tool (iconutil, Axialis, or sips) that writes the full image+mask block.","Pad the mask buffer to 2*totalBytes with zeros before calling Apply1BPPMask so underrun cannot occur.","Catch ArgumentException during ICNS decode and skip the offending icon rather than failing the whole file.","Verify the element's declared length equals the expected bytes for its 1BPP type before decoding."],"exampleFix":"// before\nif (maskData.Length >= 2 * totalBytes)\n    position = totalBytes;\nelse\n    throw new ArgumentException(\"1 BPP mask underrun parsing ICNS file\");\n\n// after — tolerate a short mask by clamping\nposition = Math.Min(totalBytes, Math.Max(0, maskData.Length - totalBytes));","handlingStrategy":"validation","validationCode":"int totalBytes = (image.Width*image.Height + 7)/8;\nbool maskOk = maskData.Length >= 2*totalBytes;\n// only call Apply1BPPMask when maskOk; otherwise pad: Array.Resize(ref maskData, 2*totalBytes);","typeGuard":"static bool HasFull1BppMask(int w, int h, byte[] data) { int t=(w*h+7)/8; return data != null && data.Length >= 2*t; }","tryCatchPattern":"try { Apply1BPPMask(maskData, bitmapData); }\ncatch (ArgumentException) { /* skip mask, keep image */ }","preventionTips":["Verify element declared length matches expected 2*ceil(W*H/8) for 1BPP icons.","Pad short mask buffers with zeros rather than throwing.","Re-export ICNS with iconutil for spec-compliant masks."],"tags":["icns","macos","icon","binary-parsing","mask"],"backgroundTag":null,"analyzedSha":"cb5d9c429c81d9796fac469da2a68efb5626946d","analyzedAt":"2026-08-13T11:51:01.370Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}