Validate string max length

This commit is contained in:
vagola 2020-01-04 12:39:31 +03:00
parent 0287fadb1e
commit d7c35639c9
3 changed files with 71 additions and 13 deletions

View File

@ -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());

View File

@ -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 {

View File

@ -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 });
} }