parser_robustness_corpus.rs (4973B)
1 #![cfg(feature = "json")] 2 3 use radroots_event::wire::{ 4 DEFAULT_EXTRA_MAX_FIELDS, DEFAULT_RAW_JSON_MAX_BYTES, DEFAULT_TAG_MAX_COUNT, EventWireError, 5 }; 6 use radroots_event_codec::{DecodeError, decode, verify}; 7 use serde_json::{Map, Value, json}; 8 9 const VALID_ID: &str = "762bee187e9e645b81ec26ade05a69b5e8398caf527be8de0d9a45311ed0c7a0"; 10 const VALID_PUBKEY: &str = "585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df"; 11 const VALID_SIGNATURE: &str = "4290da0bb6422986647bc8cd5f63bd52d49f41e7b665d3b47105b8109183e8d596f322c531d4061df53e1d2b70fda12d5d1c14f3720d7a56d9d0a03746af5109"; 12 13 fn valid_event() -> Value { 14 json!({ 15 "id": VALID_ID, 16 "pubkey": VALID_PUBKEY, 17 "created_at": 1_800_000_100u64, 18 "kind": 0u32, 19 "tags": [], 20 "content": "{\"display_name\":\"Moss Street Farm\",\"bot\":false,\"website\":\"https://mossstreet.example\",\"picture\":42}", 21 "sig": VALID_SIGNATURE 22 }) 23 } 24 25 fn encode(value: &Value) -> String { 26 serde_json::to_string(value).expect("corpus value must serialize") 27 } 28 29 fn object(value: &mut Value) -> &mut Map<String, Value> { 30 value.as_object_mut().expect("event corpus object") 31 } 32 33 #[test] 34 fn corpus_rejects_oversized_input_before_json_allocation() { 35 let raw = " ".repeat(DEFAULT_RAW_JSON_MAX_BYTES + 1); 36 let error = decode::event(raw.as_str()).expect_err("oversized event"); 37 38 assert_eq!(error.code(), "input_too_large"); 39 assert_eq!( 40 error, 41 DecodeError::InputTooLarge { 42 max: DEFAULT_RAW_JSON_MAX_BYTES, 43 actual: DEFAULT_RAW_JSON_MAX_BYTES + 1, 44 } 45 ); 46 } 47 48 #[test] 49 fn signed_event_decoder_accepts_valid_input_and_rejects_oversize_before_parsing() { 50 let encoded = encode(&valid_event()); 51 decode::signed_event(encoded.as_str()).expect("ID-valid signed event"); 52 53 let raw = " ".repeat(DEFAULT_RAW_JSON_MAX_BYTES + 1); 54 assert_eq!( 55 decode::signed_event(raw.as_str()).expect_err("oversized signed event"), 56 DecodeError::InputTooLarge { 57 max: DEFAULT_RAW_JSON_MAX_BYTES, 58 actual: DEFAULT_RAW_JSON_MAX_BYTES + 1, 59 } 60 ); 61 } 62 63 #[test] 64 fn corpus_rejects_tag_count_overflow_before_id_verification() { 65 let mut value = valid_event(); 66 object(&mut value).insert( 67 "tags".to_owned(), 68 Value::Array(vec![json!(["t"]); DEFAULT_TAG_MAX_COUNT + 1]), 69 ); 70 let error = decode::event(encode(&value).as_str()).expect_err("tag count overflow"); 71 72 assert!(matches!( 73 error, 74 DecodeError::InvalidWire(EventWireError::TooManyTags { 75 max: DEFAULT_TAG_MAX_COUNT, 76 actual, 77 }) if actual == DEFAULT_TAG_MAX_COUNT + 1 78 )); 79 } 80 81 #[test] 82 fn corpus_bounds_unknown_fields_and_nested_json() { 83 let mut accepted = valid_event(); 84 object(&mut accepted).insert("client".to_owned(), json!({"nested": [1, 2, 3]})); 85 decode::event(encode(&accepted).as_str()).expect("bounded extension field"); 86 87 let mut too_many = valid_event(); 88 for index in 0..=DEFAULT_EXTRA_MAX_FIELDS { 89 object(&mut too_many).insert(format!("extension_{index}"), Value::Null); 90 } 91 assert!(matches!( 92 decode::event(encode(&too_many).as_str()), 93 Err(DecodeError::InvalidWire( 94 EventWireError::TooManyExtraFields { 95 max: DEFAULT_EXTRA_MAX_FIELDS, 96 actual, 97 } 98 )) if actual == DEFAULT_EXTRA_MAX_FIELDS + 1 99 )); 100 101 let nested = format!( 102 "{{\"id\":\"{VALID_ID}\",\"pubkey\":\"{VALID_PUBKEY}\",\"created_at\":1800000100,\"kind\":0,\"tags\":[],\"content\":\"\",\"sig\":\"{VALID_SIGNATURE}\",\"extension\":{} }}", 103 "[".repeat(160) + "0" + "]".repeat(160).as_str() 104 ); 105 assert_eq!( 106 decode::event(nested.as_str()) 107 .expect_err("excessive nesting") 108 .code(), 109 "invalid_json" 110 ); 111 } 112 113 #[test] 114 fn corpus_rejects_malformed_signature_and_identifier_shapes() { 115 let mut malformed_signature = valid_event(); 116 object(&mut malformed_signature).insert("sig".to_owned(), json!("00")); 117 assert!(matches!( 118 decode::event(encode(&malformed_signature).as_str()), 119 Err(DecodeError::InvalidWire( 120 EventWireError::InvalidIdentifier { field: "sig", .. } 121 )) 122 )); 123 124 let mut malformed_id = valid_event(); 125 object(&mut malformed_id).insert("id".to_owned(), json!("00")); 126 assert!(matches!( 127 decode::event(encode(&malformed_id).as_str()), 128 Err(DecodeError::InvalidWire( 129 EventWireError::InvalidIdentifier { field: "id", .. } 130 )) 131 )); 132 } 133 134 #[test] 135 fn corpus_keeps_identifier_mismatch_in_the_verifier_stage() { 136 let mut mismatched = valid_event(); 137 object(&mut mismatched).insert("id".to_owned(), json!("a".repeat(64))); 138 139 let raw = decode::event(encode(&mismatched).as_str()).expect("structurally valid event"); 140 let error = verify::id(raw).expect_err("identifier mismatch"); 141 142 assert_eq!(error.code(), "id_mismatch"); 143 }