From 56a8caff922df8d597895a49f55f2150bff3adb7 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 13 Sep 2019 22:13:39 +0200 Subject: [PATCH] qapi: Restrict strings to printable ASCII RFC 8259 on string contents: All Unicode characters may be placed within the quotation marks, except for the characters that MUST be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F). The QAPI schema parser accepts both less and more than JSON: it accepts only ASCII with \u (less), and accepts control characters other than LF (new line) unescaped. How it treats unescaped non-ASCII input differs between Python 2 and Python 3. Make it accept strictly less: require printable ASCII. Drop support for \b, \f, \n, \r, \t. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20190913201349.24332-7-armbru@redhat.com> --- scripts/qapi/common.py | 28 +++++++++------------- tests/Makefile.include | 3 ++- tests/qapi-schema/string-code-point-127.err | 1 + ...unicode-str.exit => string-code-point-127.exit} | 0 tests/qapi-schema/string-code-point-127.json | 2 ++ .../{unicode-str.out => string-code-point-127.out} | 0 tests/qapi-schema/string-code-point-31.err | 1 + ...{unicode-str.exit => string-code-point-31.exit} | 0 tests/qapi-schema/string-code-point-31.json | 2 ++ .../{unicode-str.out => string-code-point-31.out} | 0 tests/qapi-schema/unicode-str.err | 1 - tests/qapi-schema/unicode-str.json | 2 -- 12 files changed, 19 insertions(+), 21 deletions(-) create mode 100644 tests/qapi-schema/string-code-point-127.err copy tests/qapi-schema/{unicode-str.exit => string-code-point-127.exit} (100%) create mode 100644 tests/qapi-schema/string-code-point-127.json copy tests/qapi-schema/{unicode-str.out => string-code-point-127.out} (100%) create mode 100644 tests/qapi-schema/string-code-point-31.err rename tests/qapi-schema/{unicode-str.exit => string-code-point-31.exit} (100%) create mode 100644 tests/qapi-schema/string-code-point-31.json rename tests/qapi-schema/{unicode-str.out => string-code-point-31.out} (100%) delete mode 100644 tests/qapi-schema/unicode-str.err delete mode 100644 tests/qapi-schema/unicode-str.json diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 54d02458b5..539b50f9ac 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -515,6 +515,7 @@ class QAPISchemaParser(object): elif self.tok in '{}:,[]': return elif self.tok == "'": + # Note: we accept only printable ASCII string = '' esc = False while True: @@ -523,17 +524,9 @@ class QAPISchemaParser(object): if ch == '\n': raise QAPIParseError(self, 'Missing terminating "\'"') if esc: - if ch == 'b': - string += '\b' - elif ch == 'f': - string += '\f' - elif ch == 'n': - string += '\n' - elif ch == 'r': - string += '\r' - elif ch == 't': - string += '\t' - elif ch == 'u': + # Note: we don't recognize escape sequences + # for control characters + if ch == 'u': value = 0 for _ in range(0, 4): ch = self.src[self.cursor] @@ -552,20 +545,21 @@ class QAPISchemaParser(object): 'For now, \\u escape ' 'only supports non-zero ' 'values up to \\u007f') - string += chr(value) - elif ch in '\\/\'"': - string += ch - else: + ch = chr(value) + elif ch not in '\\/\'"': raise QAPIParseError(self, "Unknown escape \\%s" % ch) esc = False elif ch == '\\': esc = True + continue elif ch == "'": self.val = string return - else: - string += ch + if ord(ch) < 32 or ord(ch) >= 127: + raise QAPIParseError( + self, "Funny character in string") + string += ch elif self.src.startswith('true', self.pos): self.val = True self.cursor += 3 diff --git a/tests/Makefile.include b/tests/Makefile.include index 479664f899..393cfd78f0 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -451,6 +451,8 @@ qapi-schema += returns-array-bad.json qapi-schema += returns-dict.json qapi-schema += returns-unknown.json qapi-schema += returns-whitelist.json +qapi-schema += string-code-point-31.json +qapi-schema += string-code-point-127.json qapi-schema += struct-base-clash-deep.json qapi-schema += struct-base-clash.json qapi-schema += struct-data-invalid.json @@ -462,7 +464,6 @@ qapi-schema += type-bypass-bad-gen.json qapi-schema += unclosed-list.json qapi-schema += unclosed-object.json qapi-schema += unclosed-string.json -qapi-schema += unicode-str.json qapi-schema += union-base-empty.json qapi-schema += union-base-no-discriminator.json qapi-schema += union-branch-case.json diff --git a/tests/qapi-schema/string-code-point-127.err b/tests/qapi-schema/string-code-point-127.err new file mode 100644 index 0000000000..c310910c23 --- /dev/null +++ b/tests/qapi-schema/string-code-point-127.err @@ -0,0 +1 @@ +tests/qapi-schema/string-code-point-127.json:2:14: Funny character in string diff --git a/tests/qapi-schema/unicode-str.exit b/tests/qapi-schema/string-code-point-127.exit similarity index 100% copy from tests/qapi-schema/unicode-str.exit copy to tests/qapi-schema/string-code-point-127.exit diff --git a/tests/qapi-schema/string-code-point-127.json b/tests/qapi-schema/string-code-point-127.json new file mode 100644 index 0000000000..480318a69f --- /dev/null +++ b/tests/qapi-schema/string-code-point-127.json @@ -0,0 +1,2 @@ +# We accept printable ASCII: code points 32..126. Test code point 127: +{ 'command': '' } diff --git a/tests/qapi-schema/unicode-str.out b/tests/qapi-schema/string-code-point-127.out similarity index 100% copy from tests/qapi-schema/unicode-str.out copy to tests/qapi-schema/string-code-point-127.out diff --git a/tests/qapi-schema/string-code-point-31.err b/tests/qapi-schema/string-code-point-31.err new file mode 100644 index 0000000000..45797928d9 --- /dev/null +++ b/tests/qapi-schema/string-code-point-31.err @@ -0,0 +1 @@ +tests/qapi-schema/string-code-point-31.json:2:14: Funny character in string diff --git a/tests/qapi-schema/unicode-str.exit b/tests/qapi-schema/string-code-point-31.exit similarity index 100% rename from tests/qapi-schema/unicode-str.exit rename to tests/qapi-schema/string-code-point-31.exit diff --git a/tests/qapi-schema/string-code-point-31.json b/tests/qapi-schema/string-code-point-31.json new file mode 100644 index 0000000000..f186cbd720 --- /dev/null +++ b/tests/qapi-schema/string-code-point-31.json @@ -0,0 +1,2 @@ +# We accept printable ASCII: code points 32..126. Test code point 127: +{ 'command': '' } diff --git a/tests/qapi-schema/unicode-str.out b/tests/qapi-schema/string-code-point-31.out similarity index 100% rename from tests/qapi-schema/unicode-str.out rename to tests/qapi-schema/string-code-point-31.out diff --git a/tests/qapi-schema/unicode-str.err b/tests/qapi-schema/unicode-str.err deleted file mode 100644 index f621cd6448..0000000000 --- a/tests/qapi-schema/unicode-str.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name 'é' diff --git a/tests/qapi-schema/unicode-str.json b/tests/qapi-schema/unicode-str.json deleted file mode 100644 index 5253a1b9f3..0000000000 --- a/tests/qapi-schema/unicode-str.json +++ /dev/null @@ -1,2 +0,0 @@ -# we don't support full Unicode strings, yet -{ 'command': 'é' } -- 2.11.4.GIT