{"record":{"id":"6d0a84239f7b4030","repo":"Pumpkin-MC/Pumpkin","slug":"miss-count-exceeds-limit","errorCode":null,"errorMessage":"miss_count exceeds limit","messagePattern":"miss_count exceeds limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-protocol/src/bedrock/server/client_cache_blob_status.rs","lineNumber":19,"sourceCode":"// Last verified for v2169\n\nuse std::io::{Error, Read};\n\nuse pumpkin_macros::packet;\n\nuse crate::{codec::var_uint::VarUInt, serial::PacketRead};\n\n#[packet(135)]\npub struct SClientCacheBlobStatus {\n    pub miss_hashes: Vec<u64>,\n    pub hit_hashes: Vec<u64>,\n}\n\nimpl PacketRead for SClientCacheBlobStatus {\n    fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {\n        let miss_count = VarUInt::read(reader)?.0 as usize;\n        if miss_count > 4096 {\n            return Err(Error::new(\n                std::io::ErrorKind::InvalidData,\n                \"miss_count exceeds limit\",\n            ));\n        }\n        let mut miss_hashes = Vec::with_capacity(miss_count.min(256));\n        for _ in 0..miss_count {\n            miss_hashes.push(u64::read(reader)?);\n        }\n\n        let hit_count = VarUInt::read(reader)?.0 as usize;\n        if hit_count > 4096 {\n            return Err(Error::new(\n                std::io::ErrorKind::InvalidData,\n                \"hit_count exceeds limit\",\n            ));\n        }\n        let mut hit_hashes = Vec::with_capacity(hit_count.min(256));\n        for _ in 0..hit_count {","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-protocol/src/bedrock/server/client_cache_blob_status.rs#L1-L37","documentation":"Thrown when decoding SClientCacheBlobStatus: the VarUInt miss_count read from the packet exceeds 4096. The library enforces this cap so a malicious count cannot force huge allocations or unbounded hash reads.","triggerScenarios":"Triggered by SClientCacheBlobStatus::read when the first VarUInt (miss_count) is greater than 4096.","commonSituations":"Malicious clients flooding the server, stream desynchronization reading unrelated bytes as miss_count, a client bug writing an incorrect blob status.","solutions":["Check whether the client stream is aligned; an earlier misparse shifts the VarUInt boundary.","Reduce the number of missed blobs the client reports if it genuinely exceeds 4096.","Verify client/server chunk-blob cache protocol versions agree.","Log and drop packets from peers that repeatedly send oversized counts."],"exampleFix":"// client before\nlet miss = all_missing_blobs(); // unbounded\n// after\nlet miss: Vec<_> = all_missing_blobs().into_iter().take(4096).collect();","handlingStrategy":"validation","validationCode":"fn validate_miss_count(count: u32) -> Result<(), String> {\n    if count > 4096 {\n        return Err(format!(\"miss_count {count} exceeds 4096\"));\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match SClientCacheBlobStatus::read(reader) {\n    Err(e) if e.to_string().contains(\"miss_count\") => {\n        log::warn!(\"invalid blob status packet: {e}; dropping client packet\");\n    }\n    other => other?,\n}","preventionTips":["Cap miss blob lists at 4096 entries on the client","Verify stream alignment after any variable-length field","Treat repeated violations as a malicious peer and disconnect"],"tags":["bedrock","protocol","packet-decoding","limits"],"backgroundTag":"value-out-of-range","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}