Skip to content

feat(executor): capture bounded guest stderr tail in ExecutionReport#2859

Open
fakedev9999 wants to merge 1 commit into
mainfrom
fakedev9999/executor-stderr-tail
Open

feat(executor): capture bounded guest stderr tail in ExecutionReport#2859
fakedev9999 wants to merge 1 commit into
mainfrom
fakedev9999/executor-stderr-tail

Conversation

@fakedev9999

@fakedev9999 fakedev9999 commented Jun 28, 2026

Copy link
Copy Markdown
Member

Summary

Captures the last 2048 bytes of the guest program's fd=2 (stderr) during execution and exposes it as ExecutionReport::stderr_tail: Option<String>.

Why

A guest panic writes its message and source location (panicked at <file>:<line>:<col>) to stderr right before halting non-zero, but SP1 printed that to the host and discarded it — so execute-only failures collapse to a bare HaltWithNonZeroExitCode, losing the panic detail before sp1-cluster can attach it to error_trace.

Scope

SP1-only. No sp1-cluster/network/infra wiring. No SDK or public-explorer printing; the existing host-stderr printing is preserved. fd=1 (stdout) is not captured.

Safety

Guest stderr is untrusted, attacker-controlled text. It's bounded here (keep-last 2048 bytes, lossy UTF-8) and is observability-only/additive (fail-safe to None). Downstream storage/display must sanitize and keep it internal.

Tests

cargo test -p sp1-jit stderr_tail (bounded-tail unit tests); cargo test -p sp1-sdk --features slow-tests test_execute_panic (e2e: tail contains panic message + location); cargo check -p sp1-core-executor; cargo fmt --all --check; clippy on touched crates.

Follow-up

sp1-cluster must read report.stderr_tail into the execute-only extra_data.failure_message before this is live in error_trace.

@fakedev9999 fakedev9999 force-pushed the fakedev9999/executor-stderr-tail branch from f876d27 to d298f40 Compare June 28, 2026 23:35
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
Test Old New Diff
bn_test_bn_test_fq_partial_ord 186343 186343 0.0000 %
bls12_381_tests_test_inverse_fp2_100 2230063 2230063 0.0000 %
bn_test_bn_test_g1_add_100 998839 998832 -0.0007 %
rust_crypto_rsa_test_pkcs_verify_100 28627256 29147094 1.8159 %
curve25519_dalek_test_zero_mul 71736 71736 0.0000 %
bls12_381_tests_test_sqrt_fp_100 767303 767472 0.0220 %
bn_test_bn_test_g1_msm_edge 411941 411941 0.0000 %
curve25519_dalek_ng_test_add_then_multiply 3810997 3798927 -0.3167 %
k256_test_recover_pubkey_infinity 102032 102032 0.0000 %
sha_test_sha3_expected_digest_lte_100_times 1198891 1199083 0.0160 %
curve25519_dalek_ng_test_decompressed_noncanonical 195347 195347 0.0000 %
sha_test_sha2_v0_9_9_expected_digest_lte_100_times 1265916 1267283 0.1080 %
bn_test_bn_test_fr_inverse_100 822631 822631 0.0000 %
p256_test_recover_rand_lte_100 15786751 15774996 -0.0745 %
keccack_test_expected_digest_lte_100 1721339 1724329 0.1737 %
curve25519_dalek_ng_test_zero_msm 125094 125094 0.0000 %
bn_test_bn_test_fq_sqrt_100 804031 804031 0.0000 %
bls12_381_tests_test_bls_add_100 10376534 10376534 0.0000 %
bn_test_bn_test_g1_add_neg 299549 299549 0.0000 %
bn_test_bn_test_g1_double_100 735518 735518 0.0000 %
bls12_381_tests_test_inverse_fp_100 1205483 1205483 0.0000 %
curve25519_dalek_test_ed25519_verify 13355358 13353284 -0.0155 %
k256_test_schnorr_verify 5711126 5718061 0.1214 %
curve25519_dalek_test_zero_msm 83313 83313 0.0000 %
bn_test_bn_test_fq_inverse_100 805631 805631 0.0000 %
p256_test_verify_rand_lte_100 11973473 11988317 0.1240 %
rustcrypto_bigint_test_bigint_mul_add_residue 1747305 1747305 0.0000 %
curve25519_dalek_ng_test_zero_mul 107715 107715 0.0000 %
rustcrypto_bigint_test_bigint_mul_mod_special 1785802 1785802 0.0000 %
bls12_381_tests_test_bls_double_100 6310230 6310230 0.0000 %
curve25519_dalek_test_decompressed_noncanonical 7851 7851 0.0000 %
bls12_381_tests_test_sqrt_fp2_100 1762169 1915338 8.6921 %
k256_test_verify_rand_lte_100 11711147 11716599 0.0466 %
p256_test_recover_pubkey_infinity 97138 97138 0.0000 %
secp256k1_program_test_recover_rand_lte_100 5531726 5528401 -0.0601 %
secp256k1_program_test_verify_rand_lte_100 17088260 17076190 -0.0706 %
sha_test_sha2_v0_10_8_expected_digest_lte_100_times 1360194 1356502 -0.2714 %
sha_test_sha2_v0_10_9_expected_digest_lte_100_times 1357693 1356676 -0.0749 %
k256_test_recover_high_hash_high_recid 2109523 1877333 -11.0068 %
curve25519_dalek_test_add_then_multiply 3365130 2995830 -10.9743 %
p256_test_recover_high_hash_high_recid 5213012 5674586 8.8543 %
secp256k1_program_test_verify_v0_30_0_rand_lte_100 17086129 17077090 -0.0529 %
bn_test_bn_test_g1_mul_zero 48333 48333 0.0000 %
curve25519_dalek_test_decompressed_expected_value 4561440 4481239 -1.7582 %
k256_test_point_ops_edge_cases 32652 32652 0.0000 %
secp256k1_program_test_recover_v0_30_0_rand_lte_100 5475103 5484290 0.1678 %
sha_test_sha2_v0_10_6_expected_digest_lte_100_times 1358620 1353092 -0.4069 %
k256_test_recover_rand_lte_100 4578945 4573056 -0.1286 %

@fakedev9999 fakedev9999 force-pushed the fakedev9999/executor-stderr-tail branch from d298f40 to ad68ef9 Compare June 29, 2026 10:52
A guest panic writes its message and source location to fd=2 (stderr) right
before halting with a non-zero exit code, but SP1 printed that to the host's
stderr and discarded it, so execute-only failures surfaced only as a bare
HaltWithNonZeroExitCode. Retain the last 2048 bytes of guest fd=2 output and
expose it on ExecutionReport::stderr_tail for failure debugging.

Observability only (additive, fail-safe to None). Does not print stderr in SDK
output or the explorer. Guest stderr is untrusted and bounded here; downstream
storage/display must sanitize and re-bound. sp1-cluster wiring is a follow-up.
@fakedev9999 fakedev9999 force-pushed the fakedev9999/executor-stderr-tail branch from ad68ef9 to 7de0604 Compare June 29, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant