{"record":{"id":"a7d396ae34cf133d","repo":"QL-Win/QuickLook","slug":"ds-store-block-id-out-of-range","errorCode":null,"errorMessage":"DS_Store: block id out of range","messagePattern":"DS_Store: block id out of range","errorType":"exception","errorClass":"IndexOutOfRangeException","httpStatus":null,"severity":"warning","filePath":"QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/DSStore/DSStoreExtractor.cs","lineNumber":148,"sourceCode":"                for (int k = 0; k < (int)blkcount; k++)\n                    _root.ReadUint32(); // consume entries; not needed for filename extraction\n            }\n        }\n\n        public List<string> TraverseFromRootNode()\n        {\n            if (!_toc.TryGetValue(\"DSDB\", out var tocVal))\n                return [];\n            var rootBlk = GetBlock(tocVal);\n            uint rootNode = rootBlk.ReadUint32();\n            rootBlk.Skip(4 * 4);\n            return Traverse(rootNode);\n        }\n\n        internal DSStoreBlock GetBlock(uint bid)\n        {\n            if (_offsets.Count <= (int)bid)\n                throw new IndexOutOfRangeException(\"DS_Store: block id out of range\");\n            uint addr   = _offsets[(int)bid];\n            int  offset = (int)(addr & ~0x1Fu);\n            int  size   = 1 << (int)(addr & 0x1Fu);\n            return NewBlock((uint)offset, (uint)size);\n        }\n\n        private List<string> Traverse(uint bid)\n        {\n            var filenames = new List<string>();\n            var node = GetBlock(bid);\n            uint nextPtr = node.ReadUint32();\n            uint count   = node.ReadUint32();\n\n            if (nextPtr > 0)\n            {\n                for (int i = 0; i < (int)count; i++)\n                {\n                    uint next = node.ReadUint32();","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/QL-Win/QuickLook/blob/cb5d9c429c81d9796fac469da2a68efb5626946d/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/DSStore/DSStoreExtractor.cs#L130-L166","documentation":"Thrown by DSStoreAllocator.GetBlock when a block id (bid) exceeds the number of entries in the _offsets table. The B-tree traversal references a block index that was never recorded during ReadOffsets, indicating a corrupt or inconsistent offset table.","triggerScenarios":"During Traverse/TraverseFromRootNode, a node's next-pointer or child pointer yields a bid >= _offsets.Count: corrupt B-tree pointers, a truncated offset table, or a malformed .DS_Store.","commonSituations":"Corrupt .DS_Store from disk errors or bad transfers; a file from a non-standard writer with a different offset-table layout; truncated file where ReadOffsets did not capture all entries.","solutions":["Catch IndexOutOfRangeException around GetFileNames and return filenames collected so far.","Re-copy the .DS_Store from the macOS source.","Validate that the offset-table count in the root block matches expectations before traversal.","Clamp/ignore out-of-range block ids instead of throwing."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { var names = DSStoreExtractor.GetFileNames(path); }\ncatch (IndexOutOfRangeException ex) when (ex.Message.Contains(\"block id out of range\"))\n{\n    // B-tree references a block not in the offset table; return partial results.\n    names = new List<string>();\n}","preventionTips":["Catch IndexOutOfRangeException around GetFileNames and return partial results.","Re-obtain the .DS_Store from the source.","Validate the offset-table count before traversal."],"tags":["dsstore","macos","binary-format","corruption","indexoutofrange","csharp"],"backgroundTag":null,"analyzedSha":"cb5d9c429c81d9796fac469da2a68efb5626946d","analyzedAt":"2026-08-13T11:51:01.370Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}