123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- use std::convert::TryFrom;
- use std::fmt;
- use std::io::{self, Write};
- use byteorder::{ReadBytesExt, WriteBytesExt};
- use log::*;
- use crate::wire::*;
- #[derive(PartialEq, Debug, Clone)]
- pub struct Labels {
- segments: Vec<(u8, String)>,
- }
- impl Labels {
-
-
- pub fn root() -> Self {
- Self { segments: Vec::new() }
- }
-
-
- pub fn encode(input: &str) -> Result<Self, &str> {
- let mut segments = Vec::new();
- for label in input.split('.') {
- if label.is_empty() {
- continue;
- }
- match u8::try_from(label.len()) {
- Ok(length) => {
- segments.push((length, label.to_owned()));
- }
- Err(e) => {
- warn!("Could not encode label {:?}: {}", label, e);
- return Err(label);
- }
- }
- }
- Ok(Self { segments })
- }
- }
- impl fmt::Display for Labels {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- for (_, segment) in &self.segments {
- write!(f, "{}.", segment)?;
- }
- Ok(())
- }
- }
- pub(crate) trait ReadLabels {
-
- fn read_labels(&mut self) -> Result<(Labels, u16), WireError>;
- }
- impl ReadLabels for Cursor<&[u8]> {
- fn read_labels(&mut self) -> Result<(Labels, u16), WireError> {
- let mut labels = Labels { segments: Vec::new() };
- let bytes_read = read_string_recursive(&mut labels, self, &mut Vec::new())?;
- Ok((labels, bytes_read))
- }
- }
- pub(crate) trait WriteLabels {
-
-
-
-
-
-
-
-
- fn write_labels(&mut self, input: &Labels) -> io::Result<()>;
- }
- impl<W: Write> WriteLabels for W {
- fn write_labels(&mut self, input: &Labels) -> io::Result<()> {
- for (length, label) in &input.segments {
- self.write_u8(*length)?;
- for b in label.as_bytes() {
- self.write_u8(*b)?;
- }
- }
- self.write_u8(0)?;
- Ok(())
- }
- }
- const RECURSION_LIMIT: usize = 8;
- #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
- fn read_string_recursive(labels: &mut Labels, c: &mut Cursor<&[u8]>, recursions: &mut Vec<u16>) -> Result<u16, WireError> {
- let mut bytes_read = 0;
- loop {
- let byte = c.read_u8()?;
- bytes_read += 1;
- if byte == 0 {
- break;
- }
- else if byte >= 0b_1100_0000 {
- let name_one = byte - 0b1100_0000;
- let name_two = c.read_u8()?;
- bytes_read += 1;
- let offset = u16::from_be_bytes([name_one, name_two]);
- if recursions.contains(&offset) {
- warn!("Hit previous offset ({}) decoding string", offset);
- return Err(WireError::TooMuchRecursion(recursions.clone()));
- }
- recursions.push(offset);
- if recursions.len() >= RECURSION_LIMIT {
- warn!("Hit recursion limit ({}) decoding string", RECURSION_LIMIT);
- return Err(WireError::TooMuchRecursion(recursions.clone()));
- }
- trace!("Backtracking to offset {}", offset);
- let new_pos = c.position();
- c.set_position(u64::from(offset));
- read_string_recursive(labels, c, recursions)?;
- trace!("Coming back to {}", new_pos);
- c.set_position(new_pos);
- break;
- }
-
-
- else {
- let mut name_buf = Vec::new();
- for _ in 0 .. byte {
- let c = c.read_u8()?;
- bytes_read += 1;
- name_buf.push(c);
- }
- let string = String::from_utf8_lossy(&*name_buf).to_string();
- labels.segments.push((byte, string));
- }
- }
- Ok(bytes_read)
- }
- #[cfg(test)]
- mod test {
- use super::*;
- use pretty_assertions::assert_eq;
-
-
-
-
- #[test]
- fn nothing() {
- let buf: &[u8] = &[
- 0x00,
- ];
- assert_eq!(Cursor::new(buf).read_labels(),
- Ok((Labels::root(), 1)));
- }
- #[test]
- fn one_label() {
- let buf: &[u8] = &[
- 0x03,
- b'o', b'n', b'e',
- 0x00,
- ];
- assert_eq!(Cursor::new(buf).read_labels(),
- Ok((Labels::encode("one.").unwrap(), 5)));
- }
- #[test]
- fn two_labels() {
- let buf: &[u8] = &[
- 0x03,
- b'o', b'n', b'e',
- 0x03,
- b't', b'w', b'o',
- 0x00,
- ];
- assert_eq!(Cursor::new(buf).read_labels(),
- Ok((Labels::encode("one.two.").unwrap(), 9)));
- }
- #[test]
- fn label_followed_by_backtrack() {
- let buf: &[u8] = &[
- 0x03,
- b'o', b'n', b'e',
- 0xc0, 0x06,
- 0x03,
- b't', b'w', b'o',
- 0x00,
- ];
- assert_eq!(Cursor::new(buf).read_labels(),
- Ok((Labels::encode("one.two.").unwrap(), 6)));
- }
- #[test]
- fn extremely_long_label() {
- let mut buf: Vec<u8> = vec![
- 0xbf,
- ];
- buf.extend(vec![0x65; 191]);
- buf.push(0x00);
- assert_eq!(Cursor::new(&*buf).read_labels().unwrap().1, 193);
- }
- #[test]
- fn immediate_recursion() {
- let buf: &[u8] = &[
- 0xc0, 0x00,
- ];
- assert_eq!(Cursor::new(buf).read_labels(),
- Err(WireError::TooMuchRecursion(vec![ 0 ])));
- }
- #[test]
- fn mutual_recursion() {
- let buf: &[u8] = &[
- 0xc0, 0x02,
- 0xc0, 0x00,
- ];
- let mut cursor = Cursor::new(buf);
- assert_eq!(cursor.read_labels(),
- Err(WireError::TooMuchRecursion(vec![ 2, 0 ])));
- }
- #[test]
- fn too_much_recursion() {
- let buf: &[u8] = &[
- 0xc0, 0x02,
- 0xc0, 0x04,
- 0xc0, 0x06,
- 0xc0, 0x08,
- 0xc0, 0x0A,
- 0xc0, 0x0C,
- 0xc0, 0x0E,
- 0xc0, 0x10,
- 0x00,
- ];
- let mut cursor = Cursor::new(buf);
- assert_eq!(cursor.read_labels(),
- Err(WireError::TooMuchRecursion(vec![ 2, 4, 6, 8, 10, 12, 14, 16 ])));
- }
- }
|