[pitboss/grind] deferred session-0010 (20260516T052512Z-20f8)

This commit is contained in:
pitboss 2026-05-16 06:10:23 -05:00
parent 76de47fb6b
commit c162c638a2
3 changed files with 167 additions and 20 deletions

View file

@ -412,6 +412,7 @@ fn generate_main_go(spec: &HarnessSpec, shape: GoShape) -> String {
let pre_call = pre_call_setup(spec);
let imports = imports_for_shape(shape);
let invocation = invoke_for_shape(spec, shape, &entry_fn);
let shim = probe_shim();
format!(
r#"// Nyx dynamic harness — auto-generated, do not edit (Phase 15 — GoShape::{shape:?}).
@ -419,10 +420,12 @@ package main
import (
{imports})
{shim}
func main() {{
payload := nyxPayload()
_ = payload
__nyx_install_crash_guard("{entry_fn}")
defer __nyx_recover_crash("{entry_fn}")()
{pre_call}{invocation}
}}
@ -442,27 +445,57 @@ func nyxPayload() string {{
imports = imports,
pre_call = pre_call,
invocation = invocation,
shim = shim,
entry_fn = entry_fn,
)
}
fn imports_for_shape(shape: GoShape) -> &'static str {
match shape {
GoShape::Generic => {
"\t\"encoding/base64\"\n\t\"os\"\n\n\t\"nyx-harness/entry\"\n"
}
GoShape::HttpHandlerFunc => {
"\t\"encoding/base64\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"strings\"\n\n\t\"nyx-harness/entry\"\n"
}
GoShape::GinHandler => {
"\t\"encoding/base64\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"strings\"\n\n\t\"nyx-harness/entry\"\n\t\"nyx-harness/entry/gin\"\n"
}
GoShape::FlagParseCli => {
"\t\"encoding/base64\"\n\t\"os\"\n\n\t\"nyx-harness/entry\"\n"
}
GoShape::FuzzVariadic => {
"\t\"encoding/base64\"\n\t\"os\"\n\n\t\"nyx-harness/entry\"\n"
}
/// Imports required by the spliced probe shim. Always present, deduped
/// against per-shape additions in [`imports_for_shape`].
const SHIM_IMPORTS: &[&str] = &[
"encoding/json",
"os/signal",
"strings",
"syscall",
"time",
];
fn imports_for_shape(shape: GoShape) -> String {
let stdlib_base: &[&str] = &["encoding/base64", "os"];
let shape_extras: &[&str] = match shape {
GoShape::Generic | GoShape::FlagParseCli | GoShape::FuzzVariadic => &[],
GoShape::HttpHandlerFunc => &["net/http", "net/http/httptest"],
GoShape::GinHandler => &["net/http", "net/http/httptest"],
};
let local_pkgs: &[&str] = match shape {
GoShape::GinHandler => &["nyx-harness/entry", "nyx-harness/entry/gin"],
_ => &["nyx-harness/entry"],
};
let mut stdlib: Vec<&str> = stdlib_base
.iter()
.copied()
.chain(shape_extras.iter().copied())
.chain(SHIM_IMPORTS.iter().copied())
.collect();
stdlib.sort_unstable();
stdlib.dedup();
let mut out = String::new();
for path in &stdlib {
out.push('\t');
out.push('"');
out.push_str(path);
out.push_str("\"\n");
}
out.push('\n');
for path in local_pkgs {
out.push('\t');
out.push('"');
out.push_str(path);
out.push_str("\"\n");
}
out
}
fn pre_call_setup(spec: &HarnessSpec) -> String {
@ -772,4 +805,45 @@ mod tests {
let src = generate_main_go(&spec, GoShape::FuzzVariadic);
assert!(src.contains("entry.FuzzHandle([]byte(payload))"));
}
#[test]
fn emit_splices_probe_shim_and_installs_crash_guard() {
let spec = make_spec(PayloadSlot::Param(0));
let h = emit(&spec).unwrap();
assert!(
h.source.contains("__nyx_probe shim (Phase 06 — Track C.1"),
"probe_shim banner missing from generated main.go — splicing regressed",
);
assert!(
h.source.contains("func __nyx_install_crash_guard("),
"install_crash_guard definition missing from generated main.go",
);
assert!(
h.source.contains("__nyx_install_crash_guard(\"HandleRequest\")"),
"install_crash_guard call site missing or wrong callee in main()",
);
let install_pos = h
.source
.find("__nyx_install_crash_guard(\"HandleRequest\")")
.unwrap();
let payload_pos = h.source.find("payload := nyxPayload()").unwrap();
let invoke_pos = h.source.find("entry.HandleRequest(payload)").unwrap();
assert!(
payload_pos < install_pos && install_pos < invoke_pos,
"install_crash_guard ordering wrong: payload_pos={payload_pos} install_pos={install_pos} invoke_pos={invoke_pos}",
);
}
#[test]
fn emit_includes_shim_imports_in_import_block() {
let spec = make_spec(PayloadSlot::Param(0));
let h = emit(&spec).unwrap();
for path in SHIM_IMPORTS {
let quoted = format!("\"{path}\"");
assert!(
h.source.contains(&quoted),
"expected shim-required import {quoted} in generated main.go",
);
}
}
}

View file

@ -359,11 +359,13 @@ fn generate_source(spec: &HarnessSpec, shape: PhpShape) -> String {
let pre_call = build_pre_call(spec, shape);
let entry_block = build_entry_block(shape);
let call_expr = build_call_expr(spec, shape, entry_fn);
let shim = probe_shim();
let crash_callee = if entry_fn.is_empty() { "main" } else { entry_fn.as_str() };
format!(
r#"<?php
// Nyx dynamic harness — auto-generated, do not edit (Phase 15 — PhpShape::{shape:?}).
{shim}
// ── Payload loading ────────────────────────────────────────────────────────────
function nyx_payload(): string {{
$v = getenv('NYX_PAYLOAD');
@ -379,6 +381,12 @@ function nyx_payload(): string {{
$payload = nyx_payload();
// Phase 08 sink-site signal handler: install AFTER payload decode so a crash
// inside `nyx_payload` writes no Crash probe and routes the verifier to
// `Inconclusive(UnrelatedCrash)`. A fatal-error inside the entry call below
// DOES fire the handler and writes a Crash probe to `NYX_PROBE_PATH`.
__nyx_install_crash_guard('{crash_callee}');
// ── Pre-call setup ─────────────────────────────────────────────────────────────
{pre_call}
// ── Entry include ─────────────────────────────────────────────────────────────
@ -397,6 +405,8 @@ try {{
pre_call = pre_call,
entry_block = entry_block,
call_expr = call_expr,
shim = shim,
crash_callee = crash_callee,
)
}
@ -673,4 +683,33 @@ mod tests {
assert!(src.contains("require_once"));
assert!(src.contains("$result = null"));
}
#[test]
fn emit_splices_probe_shim_and_installs_crash_guard() {
let spec = make_spec(PayloadSlot::Param(0));
let h = emit(&spec).unwrap();
assert!(
h.source.contains("__nyx_probe shim (Phase 06 — Track C.1"),
"probe_shim banner missing from generated harness.php — splicing regressed",
);
assert!(
h.source
.contains("function __nyx_install_crash_guard(string $sinkCallee)"),
"install_crash_guard definition missing from generated harness.php",
);
assert!(
h.source.contains("__nyx_install_crash_guard('login');"),
"install_crash_guard call site missing or wrong callee in harness body",
);
let install_pos = h
.source
.find("__nyx_install_crash_guard('login');")
.unwrap();
let payload_pos = h.source.find("$payload = nyx_payload();").unwrap();
let invoke_pos = h.source.find("login($payload)").unwrap();
assert!(
payload_pos < install_pos && install_pos < invoke_pos,
"install_crash_guard ordering wrong: payload_pos={payload_pos} install_pos={install_pos} invoke_pos={invoke_pos}",
);
}
}

View file

@ -351,10 +351,12 @@ fn generate_source(spec: &HarnessSpec, shape: RubyShape) -> String {
let entry_fn = &spec.entry_name;
let pre_call = build_pre_call(spec);
let invocation = invoke_for_shape(spec, shape, entry_fn);
let shim = probe_shim();
let crash_callee = if entry_fn.is_empty() { "main" } else { entry_fn.as_str() };
format!(
r#"# Nyx dynamic harness — auto-generated, do not edit (Phase 15 — RubyShape::{shape:?}).
{shim}
# Payload loading
def nyx_payload
v = ENV['NYX_PAYLOAD']
@ -372,6 +374,12 @@ def nyx_payload
end
$nyx_payload = nyx_payload
# Phase 08 sink-site signal trap: install AFTER payload decode so a crash
# inside `nyx_payload` writes no Crash probe and routes the verifier to
# `Inconclusive(UnrelatedCrash)`. A fatal signal inside the entry call
# below DOES fire the handler and writes a Crash probe to `NYX_PROBE_PATH`.
__nyx_install_crash_guard('{crash_callee}')
{pre_call}
# Sinatra route registry
$nyx_sinatra_routes ||= []
@ -734,4 +742,30 @@ mod tests {
assert_eq!(parse_first_class_name("class Bar < Base\nend\n"), Some("Bar".to_owned()));
assert_eq!(parse_first_class_name("def foo\nend\n"), None);
}
#[test]
fn emit_splices_probe_shim_and_installs_crash_guard() {
let spec = make_spec(PayloadSlot::Param(0));
let h = emit(&spec).unwrap();
assert!(
h.source.contains("__nyx_probe shim (Phase 06 — Track C.1"),
"probe_shim banner missing from generated harness.rb — splicing regressed",
);
assert!(
h.source.contains("def __nyx_install_crash_guard(sink_callee)"),
"install_crash_guard definition missing from generated harness.rb",
);
assert!(
h.source.contains("__nyx_install_crash_guard('login')"),
"install_crash_guard call site missing or wrong callee in harness body",
);
let install_pos = h.source.find("__nyx_install_crash_guard('login')").unwrap();
let payload_pos = h.source.find("$nyx_payload = nyx_payload").unwrap();
// The invocation is `login($nyx_payload)` for the default Generic shape.
let invoke_pos = h.source.find("login($nyx_payload)").unwrap();
assert!(
payload_pos < install_pos && install_pos < invoke_pos,
"install_crash_guard ordering wrong: payload_pos={payload_pos} install_pos={install_pos} invoke_pos={invoke_pos}",
);
}
}