Skip to content

x86_64 emitters stamp a transposed heap magic (0x4548504c vs 0x454C5048): refcount ops silently no-op #482

Description

@mirchaemanuel

Summary

Several x86_64 emitters stamp heap allocations with a transposed magic word, 0x4548504c (E H P L), while the canonical constant checked by the refcount helpers is X86_64_HEAP_MAGIC_HI32 = 0x454C5048 (E L P H, see src/codegen/runtime/arrays/incref.rs:14, decref_object.rs:15). Any object stamped with the transposed word fails the magic check in __rt_incref / __rt_decref_object / deep-free, so every refcount operation on it is a silent no-op on linux-x86_64 — the object can never be freed, and acquire/release bookkeeping is inert for it.

Affected stamp sites (grep 0x4548504c)

src/codegen_ir/lower_inst/objects.rs            (2: LogicException + Error throwable allocation)
src/codegen_ir/lower_inst/enums.rs              (enum ValueError/TypeError throwers)
src/codegen_ir/lower_inst/static_properties.rs
src/codegen_ir/lower_inst/builtins/math.rs
src/codegen/runtime/arrays/value_error.rs
src/codegen/runtime/system/json_throw_error.rs
src/codegen/runtime/spl/doubly_linked_list.rs
src/codegen/runtime/spl/fixed_array.rs
src/codegen/builtins/math/clamp.rs
src/codegen/builtins/strings/hash_crypto.rs
src/codegen/expr/objects/allocation.rs          (frozen legacy backend)
src/codegen/expr/objects/dispatch/enums.rs      (frozen legacy backend)

By contrast, the main throwable allocation used by user-level new (src/codegen_ir/lower_inst/objects.rs, emit_throwable_allocation) and __rt_heap_alloc itself stamp the canonical 0x454C5048….

Impact

On linux-x86_64 only: throwables and objects created through the affected paths (runtime-raised ValueError/TypeError/LogicException/Error, JSON throw errors, some SPL/math/static-property paths) leak once released paths exist for them, and any ownership balancing around them silently does nothing. This was latent while caught exceptions were never released at all; PR #477 (issue #448) makes exception releases real, so these objects now diverge from the correctly-stamped ones (they leak instead of freeing — no crash).

Full disclosure: the enums.rs occurrences include code I added in #450/#453, faithfully copying the transposed literal from the pre-existing emit_throw_value_error_from_string_result_x86_64 — the constant deserves a single named const shared by every emitter so this class of typo cannot recur.

Suggested direction

Replace every literal 0x4548504c… stamp with the canonical constant (ideally exporting one X86_64_HEAP_MAGIC_HI32-derived kind-word helper for emitters), and add a debug assertion or test that greps/validates stamped magic words against the checker constant. Legacy-backend files can be skipped per the backend freeze policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions