{"record":{"id":"1bdb04f6759d534d","repo":"Pumpkin-MC/Pumpkin","slug":"actions-len-exceeds-limit","errorCode":null,"errorMessage":"actions_len exceeds limit","messagePattern":"actions_len exceeds limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-protocol/src/bedrock/server/player_auth_input.rs","lineNumber":182,"sourceCode":"            let slots_len = VarUInt::read(buf)?.0 as usize;\n            if slots_len > 1024 {\n                return Err(Error::new(\n                    ErrorKind::InvalidData,\n                    \"slots_len exceeds limit\",\n                ));\n            }\n            legacy_slots.reserve(slots_len.min(64));\n            for _ in 0..slots_len {\n                legacy_slots.push(\n                    crate::bedrock::server::inventory_transaction::LegacySetItemSlot::read(buf)?,\n                );\n            }\n        }\n        let mut actions = Vec::new();\n        if bool::read(buf)? && bool::read(buf)? {\n            let actions_len = VarUInt::read(buf)?.0 as usize;\n            if actions_len > 1024 {\n                return Err(Error::new(\n                    ErrorKind::InvalidData,\n                    \"actions_len exceeds limit\",\n                ));\n            }\n            actions.reserve(actions_len.min(64));\n            for _ in 0..actions_len {\n                actions.push(\n                    crate::bedrock::server::inventory_transaction::InventoryAction::read(buf)?,\n                );\n            }\n        }\n        let transaction = PlayerUseItemTransactionData::read(buf)?;\n        Ok(Self {\n            legacy_request_id,\n            legacy_slots,\n            actions,\n            transaction,\n        })","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-protocol/src/bedrock/server/player_auth_input.rs#L164-L200","documentation":"Hard sanity cap in SPlayerAuthInput's item-use transaction decoding: after reading the two boolean flags and the actions_len VarUInt, values above 1024 are rejected with InvalidData before any allocation loop. The offending input is the actions_len count declared by the client — a malicious or desynchronized client claiming an absurd number of inventory actions; the guard prevents huge pre-reservations and long loops.","triggerScenarios":"PlayerAuthInput packet where both gating bools are true and the VarUInt actions_len is > 1024.","commonSituations":"Clients with huge queued transaction batches, buggy client mods, or deliberately crafted oversized packets.","solutions":["Drop the offending auth-input packet","Retain the length cap before reserving the vector","Log the oversized actions count at debug level"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let actions_len = VarUInt::read(buf)?.0 as usize;\nif actions_len > 1024 { return Err(...); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = decode(&buf) {\n    if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains(\"exceeds limit\") { drop_packet(); }\n}","preventionTips":["Enforce per-packet size limits at the transport layer too","Batch client-side actions to stay well under the 1024 cap","Unit-test decoders with counts just over the limit","Monitor for clients tripping length limits repeatedly"],"tags":["bedrock","protocol","packet-decoding","length-validation"],"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"}