From 149c92394334d3cb0c50a0700567e55d63e9d0e8 Mon Sep 17 00:00:00 2001 From: Christian Herdtweck Date: Fri, 4 Oct 2024 15:36:43 +0200 Subject: [PATCH] Fix escaping of double quotes 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 | 2 -- src/cnfvar/string.py | 2 +- test/cnfvar/test_string.py | 25 +++++++++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/cnfvar/binary.py b/src/cnfvar/binary.py index d707daa..a903e1b 100644 --- a/src/cnfvar/binary.py +++ b/src/cnfvar/binary.py @@ -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 diff --git a/src/cnfvar/string.py b/src/cnfvar/string.py index 7b8f5aa..a66c568 100644 --- a/src/cnfvar/string.py +++ b/src/cnfvar/string.py @@ -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): diff --git a/test/cnfvar/test_string.py b/test/cnfvar/test_string.py index e61e0f3..36963b4 100755 --- a/test/cnfvar/test_string.py +++ b/test/cnfvar/test_string.py @@ -22,6 +22,7 @@ # Copyright (c) 2016-2018 Intra2net AG 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) -- 1.7.1