{"record":{"id":"be82678be8614959","repo":"Pumpkin-MC/Pumpkin","slug":"extra-data-length-exceeds-limit","errorCode":null,"errorMessage":"extra_data length exceeds limit","messagePattern":"extra_data length exceeds limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-protocol/src/bedrock/server/item_stack_request.rs","lineNumber":57,"sourceCode":"impl PacketRead for StackRequestItem {\n    fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {\n        let descriptor_type = VarUInt::read(reader)?.0;\n        let _legacy_type = u8::read(reader)?;\n        let (identifier, metadata_value) = match descriptor_type {\n            0 => (None, VarInt(0)),\n            1 => (Some(String::read(reader)?), VarInt::read(reader)?),\n            _ => {\n                return Err(Error::new(\n                    ErrorKind::InvalidData,\n                    format!(\"unknown stack request item descriptor type {descriptor_type}\"),\n                ));\n            }\n        };\n        let count = i16::read(reader)? as u16;\n        let block_runtime_id = VarUInt::read(reader)?;\n        let data_len = VarUInt::read(reader)?.0 as usize;\n        if data_len > 1_048_576 {\n            return Err(Error::new(\n                ErrorKind::InvalidData,\n                \"extra_data length exceeds limit\",\n            ));\n        }\n        let mut extra_data = vec![0; data_len];\n        reader.read_exact(&mut extra_data)?;\n        Ok(Self {\n            identifier,\n            metadata_value,\n            count,\n            block_runtime_id,\n            extra_data,\n        })\n    }\n}\n\n#[derive(Debug)]\npub enum ItemStackRequestAction {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-protocol/src/bedrock/server/item_stack_request.rs#L39-L75","documentation":"Thrown while decoding an item descriptor's extra_data when its declared VarUInt length exceeds 1 MiB (1_048_576 bytes). The guard prevents the decoder from allocating an attacker-controlled buffer before read_exact. The packet is rejected with an InvalidData error.","triggerScenarios":"A client sends an ItemStackRequest where the extra_data length field for an item descriptor is > 1048576; seen with malformed packets, fuzzing, or a version mismatch that shifts field boundaries so a later field is misread as the length.","commonSituations":"Protocol version drift after a Bedrock update, hostile clients probing for allocation DoS, or corrupted network streams.","solutions":["Verify client/server protocol versions match","If the new protocol legitimately allows larger extra_data, raise the 1_048_576 limit in the decoder","Re-check the field order in the serializer for your client version to rule out offset drift"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn extra_data_len_ok(len: usize) -> bool { len <= 1_048_576 }","typeGuard":"fn bounded_len(len: u32, max: usize) -> Option<usize> { usize::try_from(len).ok().filter(|&l| l <= max) }","tryCatchPattern":"if let Err(e) = decode_item_stack_request(buf) {\n    if e.kind() == std::io::ErrorKind::InvalidData { drop_packet(peer); return Ok(()); }\n    return Err(e.into());\n}","preventionTips":["Always validate declared lengths before allocating buffers","Keep the 1 MiB cap; legitimate item extra_data is far smaller","Re-encode packets after every protocol version bump to catch offset drift"],"tags":["protocol","bedrock","deserialization","size-limit"],"backgroundTag":"payload-too-large","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}