Skip to content

pkg/mutator

Structure-aware mutation engine for generating malformed GGUF files that target specific bug classes.

import "github.com/professor-moody/crucible/pkg/mutator"

Types

Strategy

type Strategy interface {
    Name() string
    Mutate(f *gguf.File, rng *rand.Rand)
}

A single mutation operation that modifies a GGUF file in place. Each strategy targets a specific structural component of the format. See Mutation Strategies for the full list.


Category

type Category int

Mutation categories with their selection weights during fuzzing:

Constant Weight Description
CategoryHeader 10% Magic bytes, version, counts
CategoryMetadata 35% Key-value pairs, types, strings
CategoryTensorInfo 35% Tensor dimensions, types, offsets
CategoryAlignment 5% Padding and alignment values
CategoryData 5% Raw tensor data section
CategoryConsistency 10% Cross-section invariant violations

Weight distribution

Metadata and tensor info receive the highest weights because GGUF parsers spend the most code -- and have the most bugs -- in these sections. Header and alignment mutations are less frequent but target critical edge cases like division-by-zero.


Mutator

type Mutator struct {
    // unexported fields
}

The main fuzzing engine. Selects and applies mutation strategies based on category weights.

Constructor

func New(seed uint64) *Mutator

Creates a new Mutator with a deterministic PRNG seed. Using the same seed produces identical mutation sequences for reproducibility.

Methods

func (m *Mutator) Mutate(f *gguf.File) ([]byte, error)

Applies a randomly selected mutation to f and returns the serialized bytes. The original file is modified in place.

func (m *Mutator) MutateBytes(data []byte) ([]byte, error)

Convenience method that unmarshals data into a *gguf.File, applies a mutation, and returns the re-serialized result.

func (m *Mutator) AppliedMutations(f *gguf.File) ([]byte, []string, error)

Applies one or more mutations and returns:

  1. The serialized mutated file as []byte
  2. A slice of strategy names that were applied (e.g., ["header.version", "metadata.key_length"])
  3. An error if serialization fails

Strategy Factories

Functions that return all registered strategies for a given category:

func HeaderStrategies() []Strategy
func MetadataStrategies() []Strategy
func TensorInfoStrategies() []Strategy
func AlignmentStrategies() []Strategy
func DataStrategies() []Strategy
func ConsistencyStrategies() []Strategy

Each returns a slice of Strategy implementations. Useful for targeted fuzzing of a single GGUF section.


Usage

Basic mutation with reproducible seed

m := mutator.New(42) // deterministic seed

file := gguf.NewFile()
data, names, err := m.AppliedMutations(file)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Applied:", strings.Join(names, ", "))
os.WriteFile("fuzzed.gguf", data, 0644)

Mutating from raw bytes

original, _ := os.ReadFile("model.gguf")

m := mutator.New(uint64(time.Now().UnixNano()))
mutated, err := m.MutateBytes(original)
if err != nil {
    log.Fatal(err)
}

os.WriteFile("mutated.gguf", mutated, 0644)

Targeted category fuzzing

file := gguf.NewFile()
rng := rand.New(rand.NewSource(42))

for _, s := range mutator.MetadataStrategies() {
    clone := *file // shallow copy
    s.Mutate(&clone, rng)
    data, _ := gguf.Marshal(&clone)
    os.WriteFile(fmt.Sprintf("meta_%s.gguf", s.Name()), data, 0644)
}