-
Notifications
You must be signed in to change notification settings - Fork 4
poolfuzz: align hunt worker exec config with campaign mutation scheduling #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -33,3 +33,38 @@ func TestCorpusSnapshotRoundTrip(t *testing.T) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatalf("claim maps roundtrip failed") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Workers receive corpus seeds through the claim maps while the coordinator's | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // verification replay loads the frozen snapshot; both channels must yield the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // same seed tuples or the two sides schedule different inputs. Crash seeds and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // empty-InputBytes seeds are the lossy edge cases — they must degrade | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // identically on both channels. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func TestClaimMapsMatchSnapshotChannel(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| seeds := []PoolCorpusSeed{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Input: 42, InputBytes: []byte(`{"a":1}`), Energy: 3, Edge: 7, Path: 11}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Input: 99, Energy: 1, Edge: 2, Path: 3, Crash: true}, // empty InputBytes + Crash flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {InputBytes: []byte(`{"c":"x"}`), Energy: 5, Edge: 9}, // zero Input u64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| viaClaim, err := CorpusSeedsFromClaimMaps(CorpusSeedsClaimMaps(seeds)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
ast-grep outline internal/workerfuzzloop/loop.go --match 'Claim|Decode' --view expanded
rg -n -C 5 'ClaimResp|UseNumber|json.NewDecoder|json.Unmarshal' internal/workerfuzzloop
rg -n -C 6 'func u64FromAny|func CorpusSeedsFromClaimMaps|func PackInputBytesToU64' internal/fuzzengineRepository: jokeez/hackme Length of output: 22632 🏁 Script executed: sed -n '80,165p' internal/fuzzengine/corpus_snapshot.go
sed -n '1,115p' internal/fuzzengine/corpus_snapshot_test.go
sed -n '468,505p' internal/workerfuzzloop/loop.goRepository: jokeez/hackme Length of output: 5208 🏁 Script executed: rg -n -C 5 'CorpusSeeds|CorpusSeedsClaimMaps|PoolCorpusSeed' internal --glob '*.go'
sed -n '1,95p' internal/fuzzengine/corpus_snapshot.go
sed -n '1,80p' internal/workerfuzzloop/loop.goRepository: jokeez/hackme Length of output: 42035 Preserve large
Decode claim seed values with an exact numeric representation, or use a typed wire struct. Parse that representation in the conversion helpers. Add a JSON round-trip case with 🤖 Prompt for AI AgentsSource: Learnings |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatal(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapJSON, _, err := EncodeCorpusSnapshot(seeds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatal(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| viaSnapshot, err := DecodeCorpusSnapshot(snapJSON) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatal(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(viaClaim) != len(viaSnapshot) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatalf("channel sizes differ: claim %d vs snapshot %d", len(viaClaim), len(viaSnapshot)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i := range viaSnapshot { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| a, b := viaClaim[i], viaSnapshot[i] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if a.Input != b.Input || a.Energy != b.Energy || a.Edge != b.Edge || a.Path != b.Path || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string(a.InputBytes) != string(b.InputBytes) || a.Crash != b.Crash { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: rg -n 'CorpusSeedsFromClaimMaps|DecodeCorpusSnapshot|EncodeCorpusSnapshot|CorpusSeedsClaimMaps|\.Crash' internal/poolfuzz internal/workerfuzzloop internal/fuzzengine | head -110Repository: jokeez/hackme Length of output: 3941 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- corpus conversion ---'
cat -n internal/fuzzengine/corpus_snapshot.go | sed -n '1,135p'
printf '%s\n' '--- pool seed and scheduling ---'
cat -n internal/fuzzengine/pool_corpus.go | sed -n '1,90p'
cat -n internal/fuzzengine/power_schedule.go | sed -n '1,70p'
printf '%s\n' '--- worker hunt caller ---'
cat -n internal/workerfuzzloop/hunt_shard.go | sed -n '1,115p'
printf '%s\n' '--- worker loop replay/corpus caller ---'
cat -n internal/workerfuzzloop/loop.go | sed -n '540,610p'
printf '%s\n' '--- pool hunt caller ---'
cat -n internal/poolfuzz/hunt_shard.go | sed -n '35,100p'
printf '%s\n' '--- claim and replay references ---'
rg -n -C 5 'CorpusSeedsFromClaimMaps|CorpusSeedsClaimMaps|DecodeCorpusSnapshot|CrashInput|PowerSchedule|Schedule|corpus_seeds' internal/workerfuzzloop internal/poolfuzz internal/fuzzengineRepository: jokeez/hackme Length of output: 42299 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- replay definitions and seed consumers ---'
rg -n -C 8 'func ReplayShard|ReplayShardOpts|CorpusSeeds|PickWeightedSeed|SeedScheduleWeight|GuidedScheduling' internal/hunt internal/workerfuzzloop internal/poolfuzz
printf '%s\n' '--- guided Hunt claim and seed selection ---'
rg -n -C 10 'lockHuntGuidedWorkItem|PickWeightedSeed|CorpusSeeds|EncodeCorpusSnapshot|DecodeCorpusSnapshot|EnsureGuidedCorpusSeeded' internal/poolfuzz/hunt_shard.go internal/poolfuzz/corpus_store.go internal/poolfuzz
printf '%s\n' '--- replay source files ---'
fd -i -t f 'hunt|replay' internal | sortRepository: jokeez/hackme Length of output: 42409 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- scheduling selection ---'
cat -n internal/fuzzengine/pool_corpus.go | sed -n '84,180p'
printf '%s\n' '--- shard input generation ---'
cat -n internal/hunt/shard_input.go | sed -n '84,152p'
printf '%s\n' '--- coordinator guided claim ---'
cat -n internal/poolfuzz/hunt_corpus.go | sed -n '1,75p'
cat -n internal/poolfuzz/hunt_shard.go | sed -n '36,100p'
printf '%s\n' '--- replay input path ---'
cat -n internal/hunt/replay.go | sed -n '160,230p'Repository: jokeez/hackme Length of output: 15618 🏁 Script executed: #!/bin/bash
set -e
rg -n -C 4 'func (boolFromAny|cfgTruthy)|boolFromAny\(|"crash"\s*:' internal/fuzzengine internal/poolfuzz internal/workerfuzzloop internal/huntRepository: jokeez/hackme Length of output: 1182 Preserve
Suggested fix type corpusSeedWire struct {
InputU64 uint64 `json:"input_u64"`
InputBytesHex string `json:"input_bytes_hex,omitempty"`
Energy int `json:"energy"`
Edge int `json:"edge"`
Path int `json:"path"`
+ Crash bool `json:"crash,omitempty"`
}
@@
Energy: s.Energy,
Edge: s.Edge,
Path: s.Path,
+ Crash: s.Crash,
}
@@
- Input: w.InputU64, InputBytes: b, Energy: w.Energy, Edge: w.Edge, Path: w.Path,
+ Input: w.InputU64, InputBytes: b, Energy: w.Energy, Edge: w.Edge, Path: w.Path, Crash: w.Crash,
})
@@
"energy": s.Energy,
"edge": s.Edge,
"path": s.Path,
+ "crash": s.Crash,
}
@@
- Input: u, InputBytes: b, Energy: energy, Edge: edge, Path: path,
+ Input: u, InputBytes: b, Energy: energy, Edge: edge, Path: path, Crash: m["crash"] == true,
})- if a.Input != b.Input || a.Energy != b.Energy || a.Edge != b.Edge || a.Path != b.Path ||
- string(a.InputBytes) != string(b.InputBytes) || a.Crash != b.Crash {
+ if a.Input != seeds[i].Input || b.Input != seeds[i].Input ||
+ a.Energy != seeds[i].Energy || b.Energy != seeds[i].Energy ||
+ a.Edge != seeds[i].Edge || b.Edge != seeds[i].Edge ||
+ a.Path != seeds[i].Path || b.Path != seeds[i].Path ||
+ string(a.InputBytes) != string(seeds[i].InputBytes) ||
+ string(b.InputBytes) != string(seeds[i].InputBytes) ||
+ a.Crash != seeds[i].Crash || b.Crash != seeds[i].Crash {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.Fatalf("seed %d differs across channels: claim %+v vs snapshot %+v", i, a, b) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,5 +149,16 @@ func huntShardConfigFromClaim(cr ClaimResp, corpusGuided bool) map[string]any { | |
| if cr.HuntDetectLeaks { | ||
| cfg["hunt_detect_leaks"] = true | ||
| } | ||
| // Keep exec input derivation byte-identical to the coordinator's replay: | ||
| // PowerScheduleStage and the deep-havoc stack both depend on these keys. | ||
| if cr.PowerMutCap > 0 { | ||
| cfg["power_mut_cap"] = cr.PowerMutCap | ||
| } | ||
| if cr.HavocDeepV28 { | ||
| cfg["havoc_deep_v28"] = true | ||
| } | ||
| // The campaign's mutator dict is a pure function of the target id, so it can | ||
| // be rebuilt locally instead of shipped on every claim. | ||
| hunt.ApplyHuntMutatorDict(cfg, strings.TrimSpace(cr.UpstreamTargetID)) | ||
|
Comment on lines
+160
to
+162
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Workers still mutate different inputs huntShardConfigFromClaim regenerates mutator_dict from the target ID instead of carrying the effective value from the persisted campaign config. Normal Hunt creation JSON-encodes the original []byte dictionary as a base64 string that replay parses as literal bytes, and campaigns with an absent or overridden dictionary also differ, so dictionary-aware stages generate different worker and replay inputs. Agent Prompt
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
ast-grep outline internal/hunt/mutator_dict.go --match 'ApplyHuntMutatorDict|MutatorDictForTarget' --view expanded
ast-grep outline internal/poolfuzz/service.go --match 'RegisterCampaign|CampaignConfig' --view expanded
rg -n -C 5 'mutator_dict|ApplyHuntMutatorDict|MutatorDictForTarget' internal/hunt internal/poolfuzz internal/fuzzengineRepository: jokeez/hackme Length of output: 14762 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- mutator_dict.go ---'
cat -n internal/hunt/mutator_dict.go
printf '%s\n' '--- poolfuzz service.go ---'
sed -n '1,230p' internal/poolfuzz/service.go | cat -n
printf '%s\n' '--- campaign and claim references ---'
rg -n -C 8 'type Campaign|RegisterCampaign|mutator_dict|MutatorDict|UpstreamTargetID|huntShardConfigFromClaim|type Claim|Claim struct|Replay' internal/poolfuzz internal/workerfuzzloop internal/huntRepository: jokeez/hackme Length of output: 43664 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- NormalizeCampaignConfig and effective dictionary ---'
rg -n -C 12 'func NormalizeCampaignConfig|func EffectiveMutatorDict|MutatorDictForTarget|ApplyHuntMutatorDict' internal/fuzzengine internal/hunt
printf '%s\n' '--- worker campaign fixture and parity tests ---'
sed -n '70,180p' internal/workerfuzzloop/hunt_shard_test.go | cat -n
printf '%s\n' '--- claim construction and config loading ---'
rg -n -C 12 'ClaimedWork\\{|ClaimResp\\{|config_json|NormalizeCampaignConfig|json.Unmarshal.*Config|UpstreamTargetID|PowerMutCap|HavocDeepV28' internal/poolfuzz internal/workerfuzzloopRepository: jokeez/hackme Length of output: 15711 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- normalization ---'
sed -n '72,150p' internal/fuzzengine/engine.go | cat -n
printf '%s\n' '--- claim structs and claim response mapping ---'
rg -n -F 'ClaimedWork{' internal/poolfuzz
rg -n -F 'ClaimResp{' internal/workerfuzzloop
rg -n -C 15 'UpstreamTargetID' internal/poolfuzz/service.go
printf '%s\n' '--- persisted campaign config reads ---'
rg -n -C 12 'config_json|Config' internal/poolfuzz/service.go internal/poolfuzz/*.goRepository: jokeez/hackme Length of output: 45663 🏁 Script executed: set -euo pipefail
printf '%s\n' '--- NormalizeCampaignConfig ---'
sed -n '72,125p' internal/fuzzengine/engine.go | cat -n
printf '%s\n' '--- claim construction ---'
rg -n -F 'ClaimedWork{' internal/poolfuzz
rg -n -F 'UpstreamTargetID' internal/poolfuzz/service.go
printf '%s\n' '--- replay config use ---'
rg -n -C 10 'config_json|load.*config|campaign.*config|ShardSegmentExecInput' internal/poolfuzz internal/huntRepository: jokeez/hackme Length of output: 41819 🏁 Script executed: set -euo pipefail
sed -n '92,130p' internal/hunt/shard_input.go | cat -n
sed -n '131,165p' internal/workerfuzzloop/hunt_shard.go | cat -n
sed -n '30,90p' internal/poolfuzz/hunt_shard.go | cat -nRepository: jokeez/hackme Length of output: 6645 🏁 Script executed: set -euo pipefail
sed -n '118,155p' internal/hunt/shard_input.go | cat -nRepository: jokeez/hackme Length of output: 1804 Preserve the effective Hunt mutator dictionary in each claim.
Carry the effective dictionary in the claim, or normalize every Hunt campaign to 🤖 Prompt for AI Agents |
||
| return cfg | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 4239
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 42370
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 33178
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 7196
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 397
🏁 Script executed:
Repository: jokeez/hackme
Length of output: 25071
Gate Hunt claims on mutation-scheduling support.
WorkerVersionAllowedandHuntHarnessCapabledo not prove support forpower_mut_caporhavoc_deep_v28. The base worker has the same0.1.0-rc17.2version and can reportlibfuzzer_oneshot, but its claim schema and Hunt reconstruction omit both fields. It therefore uses the legacy cap12and disables deep havoc. For a campaign with a different cap orhavoc_deep_v28: true, the worker and coordinator replay can use different mutation paths and inputs.Add a dedicated mutation-scheduling capability to the claim request and reject or release Hunt work when it is absent. A version floor is also valid only if it is enforced and is newer than the base worker. Do not rely on the optional unset
HACKME_POOL_MIN_WORKER_VERSION.🤖 Prompt for AI Agents
Source: Path instructions