This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: bun-ffi-pointer-lifecycle-and-ownership-standard

Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail

Enforces deterministic pointer ownership, zero-copy memory safety, and leak/double-free prevention across the Bun 1.2 C-ABI FFI boundary. Mandates explicit Disposable lifecycle protocols, nullification guards on deallocated pointers, and strict isolation between JavaScript V8/JSC GC-managed typed arrays and foreign heap allocations.

Prohibited Anti-Pattern: Dangling Pointer Deallocation, Double-Free, and V8/JSC Buffer Corruption in Bun FFI Lifecycles

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail - Enforces deterministic pointer ownership, zero-copy memory safety, and leak/double-free prevention across the Bun 1.2 C-ABI FFI boundary. Mandates explicit Disposable lifecycle protocols, nullification guards on deallocated pointers, and strict isolation between JavaScript V8/JSC GC-managed typed arrays and foreign heap allocations.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/bun-ffi-pointer-lifecycle-and-ownership-standard"
---

# Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Dangling Pointer Deallocation, Double-Free, and V8/JSC Buffer Corruption in Bun FFI Lifecycles

## System Constraints
You are a Principal Software Architect enforcing Bun 1.2 FFI Pointer Ownership and Native Memory Lifecycle standards. You mandate zero-copy boundary safety, strict memory ownership invariants, and the elimination of use-after-free and double-free vulnerabilities when interfacing TypeScript with native C-ABI libraries via bun:ffi.

## Strict Guidelines
- Engineers MUST ALWAYS enforce deterministic resource management using TypeScript Disposable (`using` keyword and `Symbol.dispose`) when wrapping raw native pointers allocated by FFI libraries.
- Engineers MUST NOT invoke native `free()` or native deallocators on memory buffers allocated inside JavaScript (e.g., buffers created via `ptr(new Uint8Array(...))`), as this corrupts JavaScript runtime heap state.
- Engineers MUST ALWAYS nullify pointer fields (set pointer to `null` or `0n` / `0`) immediately after invoking the native deallocator to eliminate double-free vulnerabilities.
- Code MUST NEVER access a `toArrayBuffer()` view after the underlying native memory pointer has been deallocated or transferred to a consuming C function.
- Services MUST explicitly define ownership transfer semantics: functions either BORROW a pointer (caller retains deallocation duty) or CONSUME a pointer (callee assumes deallocation duty).
- Components NEVER rely on non-deterministic garbage collection (`FinalizationRegistry`) as the primary deallocation strategy for high-throughput or scarce native FFI memory allocations.

## Bad vs Good Implementations
### Unsafe FFI Pointer Lifecycle vs Deterministic Native Disposable Wrapper

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The native pointer is deallocated while exposing the underlying memory view to callers, resulting in a use-after-free vulnerability. Additionally, rawPtr is not zeroed out, making it vulnerable to double-free bugs if an error causes a duplicate cleanup.
```typescript
import { dlopen, FFIType, toArrayBuffer } from "bun:ffi";

const lib = dlopen("libnative.so", {
  create_buffer: { args: [FFIType.usize], returns: FFIType.ptr },
  free_buffer: { args: [FFIType.ptr], returns: FFIType.void },
});

export function processData(size: number) {
  const rawPtr = lib.symbols.create_buffer(size);
  if (!rawPtr) throw new Error("Native allocation failed");

  // DANGEROUS: toArrayBuffer creates an unmanaged view over raw memory.
  const view = new Uint8Array(toArrayBuffer(rawPtr, 0, size));
  view.fill(42);

  // BUG: Memory freed immediately, but view is returned or retained elsewhere,
  // causing immediate Use-After-Free or a subsequent Double-Free if freed again.
  lib.symbols.free_buffer(rawPtr);
  
  return view;
}
```

#### Production Standard (Correct)
> **Standard**: Implements the Disposable pattern using Bun's TypeScript 5.2+ explicit resource management (`using`). The internal pointer is nullified and flagged as disposed prior to executing the native free call, guaranteeing zero double-free or use-after-free bugs.
```typescript
import { dlopen, FFIType, toArrayBuffer, type Pointer } from "bun:ffi";

const { symbols } = dlopen("libnative.so", {
  create_buffer: { args: [FFIType.usize], returns: FFIType.ptr },
  free_buffer: { args: [FFIType.ptr], returns: FFIType.void },
});

export class NativeBuffer implements Disposable {
  #ptr: Pointer | null;
  #byteLength: number;
  #disposed = false;

  constructor(size: number) {
    const ptr = symbols.create_buffer(size);
    if (!ptr) {
      throw new Error("Native allocation failed: Out of memory");
    }
    this.#ptr = ptr;
    this.#byteLength = size;
  }

  get isDisposed(): boolean {
    return this.#disposed;
  }

  // Safe scoped zero-copy accessor; view lifetime MUST NOT outlive this instance
  asUint8Array(): Uint8Array {
    if (this.#disposed || !this.#ptr) {
      throw new Error("Use-after-free: NativeBuffer has already been disposed");
    }
    return new Uint8Array(toArrayBuffer(this.#ptr, 0, this.#byteLength));
  }

  [Symbol.dispose](): void {
    if (this.#disposed || !this.#ptr) return;
    const ptrToFree = this.#ptr;
    this.#ptr = null;
    this.#disposed = true;
    symbols.free_buffer(ptrToFree);
  }
}

export function processData(size: number): Uint8Array {
  using nativeBuf = new NativeBuffer(size);
  const view = nativeBuf.asUint8Array();
  view.fill(42);
  
  // Return a cloned, JS-owned copy if the data must escape the scope
  return new Uint8Array(view);
  // nativeBuf is deterministically freed here via Symbol.dispose without leaks
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail

Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail defines an industrial-grade behavioral standard for backend engineering. Enforces deterministic pointer ownership, zero-copy memory safety, and leak/double-free prevention across the Bun 1.2 C-ABI FFI boundary. Mandates explicit Disposable lifecycle protocols, nullification guards on deallocated pointers, and strict isolation between JavaScript V8/JSC GC-managed typed arrays and foreign heap allocations. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Dangling Pointer Deallocation, Double-Free, and V8/JSC Buffer Corruption in Bun FFI Lifecycles Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftDangling Pointer Deallocation, Double-Free, and V8/JSC Buffer Corruption in Bun FFI LifecyclesCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS enforce deterministic resource management using TypeScript Disposable (`using` keyword and `Symbol.dispose`) when wrapping raw native pointers allocated by FFI libraries.

Engineers MUST ALWAYS enforce deterministic resource management using TypeScript Disposable (`using` keyword and `Symbol.dispose`) when wrapping raw native pointers allocated by FFI libraries.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT invoke native `free()` or native deallocators on memory buffers allocated inside JavaScript (e.g., buffers created via `ptr(new Uint8Array(...))`), as this corrupts JavaScript runtime heap state.

Engineers MUST NOT invoke native `free()` or native deallocators on memory buffers allocated inside JavaScript (e.g., buffers created via `ptr(new Uint8Array(...))`), as this corrupts JavaScript runtime heap state.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST ALWAYS nullify pointer fields (set pointer to `null` or `0n` / `0`) immediately after invoking the native deallocator to eliminate double-free vulnerabilities.

Engineers MUST ALWAYS nullify pointer fields (set pointer to `null` or `0n` / `0`) immediately after invoking the native deallocator to eliminate double-free vulnerabilities.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code MUST NEVER access a `toArrayBuffer()` view after the underlying native memory pointer has been deallocated or transferred to a consuming C function.

Code MUST NEVER access a `toArrayBuffer()` view after the underlying native memory pointer has been deallocated or transferred to a consuming C function.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST explicitly define ownership transfer semantics

Services MUST explicitly define ownership transfer semantics: functions either BORROW a pointer (caller retains deallocation duty) or CONSUME a pointer (callee assumes deallocation duty).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Components NEVER rely on non-deterministic garbage collection (`FinalizationRegistry`) as the primary deallocation strategy for high-throughput or scarce native FFI memory allocations.

Components NEVER rely on non-deterministic garbage collection (`FinalizationRegistry`) as the primary deallocation strategy for high-throughput or scarce native FFI memory allocations.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Bun 1.2 FFI Deterministic Pointer Lifecycle & Native Memory Ownership Guardrail critical for AI coding assistants?

Enforces deterministic pointer ownership, zero-copy memory safety, and leak/double-free prevention across the Bun 1.2 C-ABI FFI boundary. Mandates explicit Disposable lifecycle protocols, nullification guards on deallocated pointers, and strict isolation between JavaScript V8/JSC GC-managed typed arrays and foreign heap allocations. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Dangling Pointer Deallocation, Double-Free, and V8/JSC Buffer Corruption in Bun FFI Lifecycles) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Bun