Browse Source

Stop treating TXT messages as UTF-8

Benjamin Sago 3 years ago
parent
commit
640818d36e

+ 24 - 24
dns/src/record/txt.rs

@@ -18,7 +18,7 @@ use crate::wire::*;
 pub struct TXT {
 
     /// The messages contained in the record.
-    pub messages: Vec<String>,
+    pub messages: Vec<Box<[u8]>>,
 }
 
 impl Wire for TXT {
@@ -50,8 +50,8 @@ impl Wire for TXT {
                 }
             }
 
-            let message = String::from_utf8_lossy(&buf).to_string();
-            trace!("Parsed message -> {:?}", message);
+            let message = buf.into_boxed_slice();
+            trace!("Parsed message -> {:?}", String::from_utf8_lossy(&message));
             messages.push(message);
 
             if total_length >= stated_length {
@@ -85,7 +85,7 @@ mod test {
 
         assert_eq!(TXT::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
                    TXT {
-                       messages: vec![ String::from("txt me") ],
+                       messages: vec![ Box::new(*b"txt me") ],
                    });
     }
 
@@ -124,15 +124,15 @@ mod test {
         assert_eq!(TXT::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
                    TXT {
                        messages: vec![
-                           String::from("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
-                                         AAAAAAAAAAAAAAAAAAAAAAAAAAA"),
+                           Box::new(*b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+                                       AAAAAAAAAAAAAAAAAAAAAAAAAAA"),
                        ],
                    });
         // did you know you can just _write_ code like this, and nobody will stop you?
@@ -171,15 +171,15 @@ mod test {
         assert_eq!(TXT::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
                    TXT {
                        messages: vec![
-                           String::from("BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
-                                         BBBBBBBBBBBBBBBBBBBBBB"),
+                           Box::new(*b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
+                                       BBBBBBBBBBBBBBBBBBBBBB"),
                        ],
                    });
     }
@@ -196,8 +196,8 @@ mod test {
         assert_eq!(TXT::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
                    TXT {
                        messages: vec![
-                           String::from("txt me"),
-                           String::from("ya beb"),
+                           Box::new(*b"txt me"),
+                           Box::new(*b"ya beb"),
                        ],
                    });
     }

+ 5 - 2
src/output.rs

@@ -276,7 +276,7 @@ impl TextFormat {
                 )
             }
             Record::TXT(txt) => {
-                let messages = txt.messages.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>();
+                let messages = txt.messages.iter().map(|t| Ascii(t).to_string()).collect::<Vec<_>>();
                 messages.join(", ")
             }
             Record::URI(uri) => {
@@ -570,8 +570,11 @@ fn json_record_data(record: Record) -> JsonValue {
             }
         }
         Record::TXT(txt) => {
+            let ms = txt.messages.into_iter()
+                        .map(|txt| String::from_utf8_lossy(&txt).to_string())
+                        .collect::<Vec<_>>();
             object! {
-                "messages": txt.messages,
+                "messages": ms,
             }
         }
         Record::URI(uri) => {

+ 1 - 0
xtests/madns/outputs/bad-utf8.txt.example.ansitxt

@@ -0,0 +1 @@
+TXT bad-utf8.txt.example. 10m00s   "\208\208\160\255"

+ 28 - 0
xtests/madns/outputs/bad-utf8.txt.example.json

@@ -0,0 +1,28 @@
+{
+  "responses": [
+    {
+      "queries": [
+        {
+          "name": "bad-utf8.txt.example.",
+          "class": "IN",
+          "type": "TXT"
+        }
+      ],
+      "answers": [
+        {
+          "name": "bad-utf8.txt.example.",
+          "class": "IN",
+          "ttl": 600,
+          "type": "TXT",
+          "data": {
+            "messages": [
+              "�Р�"
+            ]
+          }
+        }
+      ],
+      "authorities": [],
+      "additionals": []
+    }
+  ]
+}

+ 1 - 0
xtests/madns/outputs/utf8.txt.example.ansitxt

@@ -0,0 +1 @@
+TXT utf8.txt.example. 10m00s   "\240\159\146\176Cache \240\159\153\133\226\128\141\239\184\143Invalidation \226\133\139and \240\159\147\155Naming \240\159\142\179Things"

+ 28 - 0
xtests/madns/outputs/utf8.txt.example.json

@@ -0,0 +1,28 @@
+{
+  "responses": [
+    {
+      "queries": [
+        {
+          "name": "utf8.txt.example.",
+          "class": "IN",
+          "type": "TXT"
+        }
+      ],
+      "answers": [
+        {
+          "name": "utf8.txt.example.",
+          "class": "IN",
+          "ttl": 600,
+          "type": "TXT",
+          "data": {
+            "messages": [
+              "💰Cache 🙅‍️Invalidation ⅋and 📛Naming 🎳Things"
+            ]
+          }
+        }
+      ],
+      "authorities": [],
+      "additionals": []
+    }
+  ]
+}

+ 33 - 0
xtests/madns/txt-records.toml

@@ -8,6 +8,22 @@ stderr = { empty = true }
 status = 0
 tags = [ "txt", "madns" ]
 
+[[cmd]]
+name = "Running with ‘utf8.txt.example’ escapes characters in the message"
+shell = "dog --colour=always ${MADNS_ARGS:[email protected]:5301 --tcp} TXT utf8.txt.example"
+stdout = { file = "outputs/utf8.txt.example.ansitxt" }
+stderr = { empty = true }
+status = 0
+tags = [ "txt", "madns", "chars" ]
+
+[[cmd]]
+name = "Running with ‘bad-utf8.txt.example’ escapes characters in the message and does not crash"
+shell = "dog --colour=always ${MADNS_ARGS:[email protected]:5301 --tcp} TXT bad-utf8.txt.example"
+stdout = { file = "outputs/bad-utf8.txt.example.ansitxt" }
+stderr = { empty = true }
+status = 0
+tags = [ "txt", "madns", "chars" ]
+
 
 # TXT record successes (JSON)
 
@@ -20,6 +36,23 @@ status = 0
 tags = [ "txt", "madns", "json" ]
 
 
+[[cmd]]
+name = "Running with ‘utf8.txt.example --json’ interprets the response as UTF-8"
+shell = "dog --colour=always ${MADNS_ARGS:[email protected]:5301 --tcp} TXT utf8.txt.example --json | jq"
+stdout = { file = "outputs/utf8.txt.example.json" }
+stderr = { empty = true }
+status = 0
+tags = [ "txt", "madns", "chars", "json" ]
+
+[[cmd]]
+name = "Running with ‘bad-utf8.txt.example --json’ uses UTF-8 replacement characters"
+shell = "dog --colour=always ${MADNS_ARGS:[email protected]:5301 --tcp} TXT bad-utf8.txt.example --json | jq"
+stdout = { file = "outputs/bad-utf8.txt.example.json" }
+stderr = { empty = true }
+status = 0
+tags = [ "txt", "madns", "chars", "json" ]
+
+
 # TXT record invalid packets
 
 [[cmd]]