Fix escaping of double quotes
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Fri, 4 Oct 2024 13:36:43 +0000 (15:36 +0200)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Fri, 4 Oct 2024 14:08:28 +0000 (16:08 +0200)
When fixing the regular expressions for cnfvar parsing before, an old bug
came to light which did the de-escaping of double quotes in cnfvar values
too early (before regexes checked the input). Change that to give the
regexp parsers correctly escaped quotes and de-escape them only after the
initial parsing.

Add unittests to check this behaviour

src/cnfvar/binary.py
src/cnfvar/string.py
test/cnfvar/test_string.py

index d707daa..a903e1b 100644 (file)
@@ -118,8 +118,6 @@ class CnfBinary:
         # TODO: should error handling be improved so error messages
         # from the binary are converted into specific exceptions types?
         output = cls.run_cmd(cmd, encoding=encoding).stdout.strip()
-        # remove escape chars (such as '//')
-        output = output.replace('\\"', '"')
         return output
 
     @classmethod
index 7b8f5aa..a66c568 100644 (file)
@@ -172,7 +172,7 @@ def marshal_in_varname(varname):
 
 
 def marshal_in_data(data):
-    return from_latin1(data) if data is not None else ""
+    return from_latin1(data).replace(r"\"", "\"") if data is not None else ""
 
 
 def marshal_in_comment(comment):
index e61e0f3..36963b4 100755 (executable)
@@ -22,6 +22,7 @@
 # Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
 
 import os
+import json
 import unittest
 
 from src.cnfvar import string as cnfvar_old
@@ -140,6 +141,15 @@ demo_cnf_escaped_quotes = r"""
 4 HERE_BE_QUOTES,3: "unquo\\\\\"\"table"
 """
 
+demo_bad_quotes = '1 BAD_VALUE,0: "\""'
+
+demo_cnf_quoted_json = r''.join([
+    r'1 AD_MACHINE_CREDENTIALS,0: "{\"Reserved Flags\":\"0\",',
+    r'\"Join Time\":\"20241001071550.162557Z\",\"Computer Name\":\"MIS1\",',
+    r'\"Account Name\":\"MIS1$\",\"Secure Channel Type\":2,\"Trust Flags\":26}"'
+])
+
+
 #
 #                                 test class
 #
@@ -170,6 +180,7 @@ class CnfVarUnittest(unittest.TestCase):
         with open(os.devnull, "w") as devnull:
             print(cnf, file=devnull)
 
+    @unittest.skip("todo: this does not add anything to `test_print_cnf`")
     def test_print_cnf_garbage(self):
         try:
             with open(os.devnull, "w") as devnull:
@@ -179,8 +190,18 @@ class CnfVarUnittest(unittest.TestCase):
 
     def test_parse_cnf_quotes(self):
         cnf = cnfvar_old.read_cnf(demo_cnf_escaped_quotes)
-        with open(os.devnull, "w") as devnull:
-            print(demo_invalid_cnfvar, file=devnull)
+        self.assertEqual(len(cnf["cnf"]), 4)
+
+    def test_parse_bad_cnf_quotes(self):
+        self.assertRaises(cnfvar_old.MalformedCNF,
+                          cnfvar_old.read_cnf,
+                          demo_bad_quotes)
+
+    def test_parse_quoted_json(self):
+        cnf = cnfvar_old.read_cnf(demo_cnf_quoted_json)
+        dat = json.loads(cnf["cnf"][0]["data"])
+        self.assertIn("Computer Name", dat)
+        self.assertIn("Account Name", dat)
 
     def test_read_nonascii(self):
         cnf = cnfvar_old.read_cnf(demo_nonascii)