{"record":{"id":"c6b90c82413160d7","repo":"microsoft/FASTER","slug":"physical-pointer-returned-by-allocator-de-reference-pointer-c6b90c","errorCode":null,"errorMessage":"Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set (otherwise, set ForceUnpinnedAllocation to true)","messagePattern":"Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set \\(otherwise, set ForceUnpinnedAllocation to true\\)","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/Allocator/MallocFixedPageSize.cs","lineNumber":188,"sourceCode":"        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ref T Get(long index)\n        {\n            if (ReturnPhysicalAddress)\n                throw new FasterException(\"Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get\");\n            Debug.Assert(index != kInvalidAllocationIndex, \"Invalid allocation index\");\n            return ref values[index >> PageSizeBits][index & PageSizeMask];\n        }\n\n        /// <summary>\n        /// Set object\n        /// </summary>\n        /// <param name=\"index\"></param>\n        /// <param name=\"value\"></param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long index, ref T value)\n        {\n            if (ReturnPhysicalAddress)\n                throw new FasterException(\"Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set (otherwise, set ForceUnpinnedAllocation to true)\");\n            Debug.Assert(index != kInvalidAllocationIndex, \"Invalid allocation index\");\n            values[index >> PageSizeBits][index & PageSizeMask] = value;\n        }\n\n        /// <summary>\n        /// Free object\n        /// </summary>\n        /// <param name=\"pointer\"></param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Free(long pointer)\n        {\n            if (!ReturnPhysicalAddress)\n                values[pointer >> PageSizeBits][pointer & PageSizeMask] = default;\n            freeList.Enqueue(pointer);\n        }\n\n        internal int FreeListCount => freeList.Count;   // For test\n","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Allocator/MallocFixedPageSize.cs#L170-L206","documentation":"Same family as Get: when MallocFixedPageSize is in physical-address mode (ReturnPhysicalAddress), Set(long index, ref T value) is disabled because writes must go through the raw pointer, and record pinning is managed by the heap container. Calling Set throws FasterException; either dereference the physical address to write, or configure ForceUnpinnedAllocation if pinned physical pointers are not used.","triggerScenarios":"Calling allocator.Set(index, ref value) on a ReturnPhysicalAddress = true MallocFixedPageSize; seen in tests/code like BasicIHeapContainerMallocFPSTest paths that write through IHeapContainer against physical-address allocators.","commonSituations":"Reusing Set()-based write helpers after enabling physical-address mode; writing to allocator slots directly in custom heap containers or recovery code without dereferencing pointers.","solutions":["Write via the physical pointer: *(T*)allocator.GetPhysicalAddress(index) = value; (or Unsafe.As/ref dereference)","Set ForceUnpinnedAllocation = true in the allocator configuration if unpinning is intended and Set should be allowed","Reconfigure the allocator with ReturnPhysicalAddress = false when Set/Get object access is required","Update shared write helpers to branch on allocator mode like read helpers"],"exampleFix":"// before\nallocator.Set(index, ref newValue);\n// after\nif (allocator.ReturnPhysicalAddress)\n{\n    *(T*)allocator.GetPhysicalAddress(index) = newValue;\n}\nelse\n{\n    allocator.Set(index, ref newValue);\n}","handlingStrategy":"type-guard","validationCode":"// Check allocator mode before writing\nif (allocator.ReturnPhysicalAddress)\n    *(T*)allocator.GetPhysicalAddress(index) = value;\nelse\n    allocator.Set(index, ref value);","typeGuard":"static bool RequiresPointerWrite(MallocFixedPageSize<T> a) => a.ReturnPhysicalAddress;","tryCatchPattern":"try\n{\n    allocator.Set(index, ref value);\n}\ncatch (FasterException ex) when (ex.Message.Contains(\"Physical pointer returned by allocator\"))\n{\n    *(T*)allocator.GetPhysicalAddress(index) = value;\n}","preventionTips":["In physical-address mode, always write through GetPhysicalAddress dereference","If Set is required, configure ForceUnpinnedAllocation=true at allocator construction","Mirror the read-side branching in all write helpers","Use IHeapContainer consistently when the allocator is in physical-address mode"],"tags":["faster","allocator","pointer-access","misconfiguration"],"backgroundTag":"invalid-state-transition","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}