Validate string max length
This commit is contained in:
parent
0287fadb1e
commit
d7c35639c9
@ -37,6 +37,13 @@ fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|||||||
let unparsed_meta = get_packet_field_meta(field);
|
let unparsed_meta = get_packet_field_meta(field);
|
||||||
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
||||||
|
|
||||||
|
// This is special case because max length are used only for strings.
|
||||||
|
if let Some(max_length) = parsed_meta.max_length {
|
||||||
|
return quote! {
|
||||||
|
crate::EncoderWriteExt::write_string(writer, &self.#name, #max_length)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let module = parsed_meta.module.as_deref().unwrap_or("Encoder");
|
let module = parsed_meta.module.as_deref().unwrap_or("Encoder");
|
||||||
let module_ident = Ident::new(&module, Span::call_site());
|
let module_ident = Ident::new(&module, Span::call_site());
|
||||||
|
|
||||||
@ -65,6 +72,13 @@ fn impl_decoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|||||||
let unparsed_meta = get_packet_field_meta(field);
|
let unparsed_meta = get_packet_field_meta(field);
|
||||||
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
||||||
|
|
||||||
|
// This is special case because max length are used only for strings.
|
||||||
|
if let Some(max_length) = parsed_meta.max_length {
|
||||||
|
return quote! {
|
||||||
|
let #name = crate::DecoderReadExt::read_string(reader, #max_length)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match parsed_meta.module {
|
match parsed_meta.module {
|
||||||
Some(module) => {
|
Some(module) => {
|
||||||
let module_ident = Ident::new(&module, Span::call_site());
|
let module_ident = Ident::new(&module, Span::call_site());
|
||||||
|
@ -236,8 +236,8 @@ mod tests {
|
|||||||
ChunkData, ClientBoundChatMessage, ClientBoundKeepAlive, GameMode, JoinGame,
|
ChunkData, ClientBoundChatMessage, ClientBoundKeepAlive, GameMode, JoinGame,
|
||||||
MessagePosition, ServerBoundChatMessage, ServerBoundKeepAlive,
|
MessagePosition, ServerBoundChatMessage, ServerBoundKeepAlive,
|
||||||
};
|
};
|
||||||
use crate::Decoder;
|
use crate::{DecodeError, Encoder, EncoderWriteExt, STRING_MAX_LENGTH};
|
||||||
use crate::Encoder;
|
use crate::{Decoder, EncodeError};
|
||||||
use nbt::CompoundTag;
|
use nbt::CompoundTag;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
@ -266,6 +266,50 @@ mod tests {
|
|||||||
assert_eq!(chat_message.message, "hello server!");
|
assert_eq!(chat_message.message, "hello server!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_server_bound_chat_message_encode_invalid_length() {
|
||||||
|
let chat_message = ServerBoundChatMessage {
|
||||||
|
message: "abc".repeat(100),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
let encode_error = chat_message
|
||||||
|
.encode(&mut vec)
|
||||||
|
.err()
|
||||||
|
.expect("Expected error `StringTooLong` because message has invalid length");
|
||||||
|
|
||||||
|
match encode_error {
|
||||||
|
EncodeError::StringTooLong { length, max_length } => {
|
||||||
|
assert_eq!(length, 300);
|
||||||
|
assert_eq!(max_length, 256);
|
||||||
|
}
|
||||||
|
_ => panic!("Expected `StringTooLong` but got `{:?}`", encode_error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_server_bound_chat_message_decode_invalid_length() {
|
||||||
|
let message = "abc".repeat(100);
|
||||||
|
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
vec.write_string(&message, STRING_MAX_LENGTH).unwrap();
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(vec);
|
||||||
|
|
||||||
|
let decode_error = ServerBoundChatMessage::decode(&mut cursor)
|
||||||
|
.err()
|
||||||
|
.expect("Expected error `StringTooLong` because message has invalid length");
|
||||||
|
|
||||||
|
match decode_error {
|
||||||
|
DecodeError::StringTooLong { length, max_length } => {
|
||||||
|
assert_eq!(length, 300);
|
||||||
|
assert_eq!(max_length, 256);
|
||||||
|
}
|
||||||
|
_ => panic!("Expected `StringTooLong` but got `{:?}`", decode_error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_client_bound_chat_message_encode() {
|
fn test_client_bound_chat_message_encode() {
|
||||||
let chat_message = ClientBoundChatMessage {
|
let chat_message = ClientBoundChatMessage {
|
||||||
|
@ -25,8 +25,8 @@ pub mod status;
|
|||||||
/// Current supported protocol version.
|
/// Current supported protocol version.
|
||||||
pub const PROTOCOL_VERSION: u32 = 498;
|
pub const PROTOCOL_VERSION: u32 = 498;
|
||||||
/// Protocol limits maximum string length.
|
/// Protocol limits maximum string length.
|
||||||
const STRING_MAX_LENGTH: u32 = 32_768;
|
const STRING_MAX_LENGTH: u16 = 32_768;
|
||||||
const HYPHENATED_UUID_LENGTH: u32 = 36;
|
const HYPHENATED_UUID_LENGTH: u16 = 36;
|
||||||
|
|
||||||
/// Possible errors while encoding packet.
|
/// Possible errors while encoding packet.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -36,7 +36,7 @@ pub enum EncodeError {
|
|||||||
/// String length.
|
/// String length.
|
||||||
length: usize,
|
length: usize,
|
||||||
/// Max string length.
|
/// Max string length.
|
||||||
max_length: u32,
|
max_length: u16,
|
||||||
},
|
},
|
||||||
IOError {
|
IOError {
|
||||||
io_error: IoError,
|
io_error: IoError,
|
||||||
@ -68,9 +68,9 @@ pub enum DecodeError {
|
|||||||
/// String length can't be more than provided value.
|
/// String length can't be more than provided value.
|
||||||
StringTooLong {
|
StringTooLong {
|
||||||
/// String length.
|
/// String length.
|
||||||
length: u32,
|
length: usize,
|
||||||
/// Max string length.
|
/// Max string length.
|
||||||
max_length: u32,
|
max_length: u16,
|
||||||
},
|
},
|
||||||
IOError {
|
IOError {
|
||||||
io_error: IoError,
|
io_error: IoError,
|
||||||
@ -140,7 +140,7 @@ trait Decoder {
|
|||||||
trait EncoderWriteExt {
|
trait EncoderWriteExt {
|
||||||
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError>;
|
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError>;
|
||||||
|
|
||||||
fn write_string(&mut self, value: &str, max_length: u32) -> Result<(), EncodeError>;
|
fn write_string(&mut self, value: &str, max_length: u16) -> Result<(), EncodeError>;
|
||||||
|
|
||||||
fn write_byte_array(&mut self, value: &[u8]) -> Result<(), EncodeError>;
|
fn write_byte_array(&mut self, value: &[u8]) -> Result<(), EncodeError>;
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ trait EncoderWriteExt {
|
|||||||
trait DecoderReadExt {
|
trait DecoderReadExt {
|
||||||
fn read_bool(&mut self) -> Result<bool, DecodeError>;
|
fn read_bool(&mut self) -> Result<bool, DecodeError>;
|
||||||
|
|
||||||
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError>;
|
fn read_string(&mut self, max_length: u16) -> Result<String, DecodeError>;
|
||||||
|
|
||||||
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ impl<W: Write> EncoderWriteExt for W {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_string(&mut self, value: &str, max_length: u32) -> Result<(), EncodeError> {
|
fn write_string(&mut self, value: &str, max_length: u16) -> Result<(), EncodeError> {
|
||||||
let length = value.len();
|
let length = value.len();
|
||||||
|
|
||||||
if length > max_length as usize {
|
if length > max_length as usize {
|
||||||
@ -224,10 +224,10 @@ impl<R: Read> DecoderReadExt for R {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError> {
|
fn read_string(&mut self, max_length: u16) -> Result<String, DecodeError> {
|
||||||
let length = self.read_var_i32()? as u32;
|
let length = self.read_var_i32()? as usize;
|
||||||
|
|
||||||
if length > max_length as u32 {
|
if length as u16 > max_length {
|
||||||
return Err(DecodeError::StringTooLong { length, max_length });
|
return Err(DecodeError::StringTooLong { length, max_length });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user