Browse Source

Stop treating HINFO responses as UTF-8

Benjamin Sago 3 years ago
parent
commit
894a074f3c

+ 10 - 14
dns/src/record/hinfo.rs

@@ -18,10 +18,10 @@ use crate::wire::*;
 pub struct HINFO {
 
     /// The CPU field, specifying the CPU type.
-    pub cpu: String,
+    pub cpu: Box<[u8]>,
 
     /// The OS field, specifying the operating system.
-    pub os: String,
+    pub os: Box<[u8]>,
 }
 
 impl Wire for HINFO {
@@ -34,20 +34,16 @@ impl Wire for HINFO {
         let cpu_length = c.read_u8()?;
         trace!("Parsed CPU length -> {:?}", cpu_length);
 
-        let mut cpu_buffer = vec![0_u8; usize::from(cpu_length)];
-        c.read_exact(&mut cpu_buffer)?;
-
-        let cpu = String::from_utf8_lossy(&cpu_buffer).to_string();
-        trace!("Parsed CPU -> {:?}", cpu);
+        let mut cpu = vec![0_u8; usize::from(cpu_length)].into_boxed_slice();
+        c.read_exact(&mut cpu)?;
+        trace!("Parsed CPU -> {:?}", String::from_utf8_lossy(&cpu));
 
         let os_length = c.read_u8()?;
         trace!("Parsed OS length -> {:?}", os_length);
 
-        let mut os_buffer = vec![0_u8; usize::from(os_length)];
-        c.read_exact(&mut os_buffer)?;
-
-        let os = String::from_utf8_lossy(&os_buffer).to_string();
-        trace!("Parsed OS -> {:?}", cpu);
+        let mut os = vec![0_u8; usize::from(os_length)].into_boxed_slice();
+        c.read_exact(&mut os)?;
+        trace!("Parsed OS -> {:?}", String::from_utf8_lossy(&os));
 
         let length_after_labels = 1 + u16::from(cpu_length) + 1 + u16::from(os_length);
         if stated_length == length_after_labels {
@@ -80,8 +76,8 @@ mod test {
 
         assert_eq!(HINFO::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
                    HINFO {
-                       cpu: String::from("some-kinda-cpu"),
-                       os: String::from("some-kinda-os"),
+                       cpu: Box::new(*b"some-kinda-cpu"),
+                       os: Box::new(*b"some-kinda-os"),
                    });
     }
 

+ 3 - 3
src/output.rs

@@ -212,7 +212,7 @@ impl TextFormat {
                 format!("{:?}", eui64.formatted_address())
             }
             Record::HINFO(hinfo) => {
-                format!("{:?} {:?}", hinfo.cpu, hinfo.os)
+                format!("{} {}", Ascii(&hinfo.cpu), Ascii(&hinfo.os))
             }
             Record::LOC(loc) => {
                 format!("{} ({}, {}) ({}, {}, {})",
@@ -490,8 +490,8 @@ fn json_record_data(record: Record) -> JsonValue {
         }
         Record::HINFO(hinfo) => {
             object! {
-                "cpu": hinfo.cpu,
-                "os": hinfo.os,
+                "cpu": String::from_utf8_lossy(&hinfo.cpu).to_string(),
+                "os": String::from_utf8_lossy(&hinfo.os).to_string(),
             }
         }
         Record::LOC(loc) => {

+ 31 - 0
xtests/madns/hinfo-records.toml

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

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

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

+ 27 - 0
xtests/madns/outputs/bad-utf8.hinfo.example.json

@@ -0,0 +1,27 @@
+{
+  "responses": [
+    {
+      "queries": [
+        {
+          "name": "bad-utf8.hinfo.example.",
+          "class": "IN",
+          "type": "HINFO"
+        }
+      ],
+      "answers": [
+        {
+          "name": "bad-utf8.hinfo.example.",
+          "class": "IN",
+          "ttl": 600,
+          "type": "HINFO",
+          "data": {
+            "cpu": "�Р�",
+            "os": "�Р�"
+          }
+        }
+      ],
+      "authorities": [],
+      "additionals": []
+    }
+  ]
+}

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

@@ -0,0 +1 @@
+HINFO utf8.hinfo.example. 10m00s   "some\240\159\140\180kinda\240\159\140\180cpu" "some\240\159\140\180kinda\240\159\140\180os"

+ 27 - 0
xtests/madns/outputs/utf8.hinfo.example.json

@@ -0,0 +1,27 @@
+{
+  "responses": [
+    {
+      "queries": [
+        {
+          "name": "utf8.hinfo.example.",
+          "class": "IN",
+          "type": "HINFO"
+        }
+      ],
+      "answers": [
+        {
+          "name": "utf8.hinfo.example.",
+          "class": "IN",
+          "ttl": 600,
+          "type": "HINFO",
+          "data": {
+            "cpu": "some🌴kinda🌴cpu",
+            "os": "some🌴kinda🌴os"
+          }
+        }
+      ],
+      "authorities": [],
+      "additionals": []
+    }
+  ]
+}