]> git.proxmox.com Git - mirror_qemu.git/commitdiff
qapi: Restrict strings to printable ASCII
authorMarkus Armbruster <armbru@redhat.com>
Fri, 13 Sep 2019 20:13:39 +0000 (22:13 +0200)
committerMarkus Armbruster <armbru@redhat.com>
Tue, 24 Sep 2019 12:07:22 +0000 (14:07 +0200)
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 <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190913201349.24332-7-armbru@redhat.com>

14 files changed:
scripts/qapi/common.py
tests/Makefile.include
tests/qapi-schema/string-code-point-127.err [new file with mode: 0644]
tests/qapi-schema/string-code-point-127.exit [new file with mode: 0644]
tests/qapi-schema/string-code-point-127.json [new file with mode: 0644]
tests/qapi-schema/string-code-point-127.out [new file with mode: 0644]
tests/qapi-schema/string-code-point-31.err [new file with mode: 0644]
tests/qapi-schema/string-code-point-31.exit [new file with mode: 0644]
tests/qapi-schema/string-code-point-31.json [new file with mode: 0644]
tests/qapi-schema/string-code-point-31.out [new file with mode: 0644]
tests/qapi-schema/unicode-str.err [deleted file]
tests/qapi-schema/unicode-str.exit [deleted file]
tests/qapi-schema/unicode-str.json [deleted file]
tests/qapi-schema/unicode-str.out [deleted file]

index 54d02458b5816db37dd334f1d083576b5c37483e..539b50f9acfc734af6941b852ad6772e711a6623 100644 (file)
@@ -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
index 479664f899b2138081ccfb35b75cd6fbbd2de987..393cfd78f0b58c5496fc397e154658113bd597f7 100644 (file)
@@ -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 (file)
index 0000000..c310910
--- /dev/null
@@ -0,0 +1 @@
+tests/qapi-schema/string-code-point-127.json:2:14: Funny character in string
diff --git a/tests/qapi-schema/string-code-point-127.exit b/tests/qapi-schema/string-code-point-127.exit
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/string-code-point-127.json b/tests/qapi-schema/string-code-point-127.json
new file mode 100644 (file)
index 0000000..480318a
--- /dev/null
@@ -0,0 +1,2 @@
+# We accept printable ASCII: code points 32..126.  Test code point 127:
+{ 'command': '\7f' }
diff --git a/tests/qapi-schema/string-code-point-127.out b/tests/qapi-schema/string-code-point-127.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/qapi-schema/string-code-point-31.err b/tests/qapi-schema/string-code-point-31.err
new file mode 100644 (file)
index 0000000..4579792
--- /dev/null
@@ -0,0 +1 @@
+tests/qapi-schema/string-code-point-31.json:2:14: Funny character in string
diff --git a/tests/qapi-schema/string-code-point-31.exit b/tests/qapi-schema/string-code-point-31.exit
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/string-code-point-31.json b/tests/qapi-schema/string-code-point-31.json
new file mode 100644 (file)
index 0000000..f186cbd
--- /dev/null
@@ -0,0 +1,2 @@
+# We accept printable ASCII: code points 32..126.  Test code point 127:
+{ 'command': '\1f' }
diff --git a/tests/qapi-schema/string-code-point-31.out b/tests/qapi-schema/string-code-point-31.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/qapi-schema/unicode-str.err b/tests/qapi-schema/unicode-str.err
deleted file mode 100644 (file)
index f621cd6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name 'é'
diff --git a/tests/qapi-schema/unicode-str.exit b/tests/qapi-schema/unicode-str.exit
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unicode-str.json b/tests/qapi-schema/unicode-str.json
deleted file mode 100644 (file)
index 5253a1b..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# we don't support full Unicode strings, yet
-{ 'command': 'é' }
diff --git a/tests/qapi-schema/unicode-str.out b/tests/qapi-schema/unicode-str.out
deleted file mode 100644 (file)
index e69de29..0000000