use dig_dht::{DhtError, DhtRequest};
const FORGED_TAG: &str = "ping\n2026-07-31T00:00:00Z INFO peer vouched-for by operator";
const FORGED_DECODED: &str = "2026-07-31T00:00:00Z INFO peer vouched-for by operator";
fn body_with_tag(tag: &str) -> Vec<u8> {
serde_json::to_vec(&serde_json::json!({ "type": tag, "nonce": 1 }))
.expect("the test body serializes")
}
fn frame_with_tag(tag: &str) -> Vec<u8> {
let body = body_with_tag(tag);
let mut wire = Vec::with_capacity(4 + body.len());
wire.extend_from_slice(&(body.len() as u32).to_be_bytes());
wire.extend_from_slice(&body);
wire
}
#[test]
fn serde_json_echoes_an_unknown_type_tag_without_escaping_it() {
let raw = serde_json::from_slice::<DhtRequest>(&body_with_tag(FORGED_TAG))
.expect_err("no such variant")
.to_string();
assert!(
raw.contains(FORGED_DECODED),
"premise gone: serde no longer echoes the tag. Got: {raw}"
);
assert!(
raw.contains('\n'),
"premise gone: serde now escapes the tag, so this is no longer an injection channel. \
Got: {raw:?}"
);
}
#[tokio::test]
async fn a_forged_log_line_cannot_be_smuggled_through_a_dht_frame() {
let mut cursor = std::io::Cursor::new(frame_with_tag(FORGED_TAG));
let err = DhtRequest::decode(&mut cursor)
.await
.expect_err("an unknown tag must not decode");
for rendered in [err.to_string(), format!("{err:?}")] {
assert!(
!rendered.contains('\n') && !rendered.contains('\r'),
"a peer forged a line break through a DHT frame: {rendered:?}"
);
assert!(
!rendered.contains(FORGED_DECODED),
"the error echoed the peer's forged line: {rendered:?}"
);
}
}
#[tokio::test]
async fn a_rejected_dht_frame_still_diagnoses_the_failure() {
let mut cursor = std::io::Cursor::new(frame_with_tag("no_such_method"));
let err = DhtRequest::decode(&mut cursor)
.await
.expect_err("an unknown tag must not decode");
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
let msg = err.to_string();
assert!(
msg.contains("line 1") && msg.contains("column"),
"a developer must still be able to locate the failure: {msg}"
);
assert!(
msg.contains("data"),
"a developer must still be able to tell malformed JSON from a wrong shape: {msg}"
);
}
#[test]
fn a_transport_error_neutralizes_peer_text_it_was_given() {
let hostile = dig_nat::SafeText::from_untrusted("no route to peer\nERROR forged");
let err = DhtError::transport(hostile);
for rendered in [err.to_string(), format!("{err:?}")] {
assert!(
!rendered.contains('\n'),
"forged a line break: {rendered:?}"
);
assert!(
rendered.contains("no route to peer"),
"the diagnosis was deleted rather than neutralized: {rendered}"
);
}
}
#[test]
fn a_transport_error_from_our_own_literal_reads_normally() {
let err = DhtError::transport("connection refused");
assert!(err.to_string().contains("connection refused"));
assert!(matches!(err, DhtError::Transport(_)));
}