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 <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20190913201349.24332-7-armbru@redhat.com>
This commit is contained in:
parent
05d6ecd049
commit
56a8caff92
@ -515,6 +515,7 @@ class QAPISchemaParser(object):
|
|||||||
elif self.tok in '{}:,[]':
|
elif self.tok in '{}:,[]':
|
||||||
return
|
return
|
||||||
elif self.tok == "'":
|
elif self.tok == "'":
|
||||||
|
# Note: we accept only printable ASCII
|
||||||
string = ''
|
string = ''
|
||||||
esc = False
|
esc = False
|
||||||
while True:
|
while True:
|
||||||
@ -523,17 +524,9 @@ class QAPISchemaParser(object):
|
|||||||
if ch == '\n':
|
if ch == '\n':
|
||||||
raise QAPIParseError(self, 'Missing terminating "\'"')
|
raise QAPIParseError(self, 'Missing terminating "\'"')
|
||||||
if esc:
|
if esc:
|
||||||
if ch == 'b':
|
# Note: we don't recognize escape sequences
|
||||||
string += '\b'
|
# for control characters
|
||||||
elif ch == 'f':
|
if ch == 'u':
|
||||||
string += '\f'
|
|
||||||
elif ch == 'n':
|
|
||||||
string += '\n'
|
|
||||||
elif ch == 'r':
|
|
||||||
string += '\r'
|
|
||||||
elif ch == 't':
|
|
||||||
string += '\t'
|
|
||||||
elif ch == 'u':
|
|
||||||
value = 0
|
value = 0
|
||||||
for _ in range(0, 4):
|
for _ in range(0, 4):
|
||||||
ch = self.src[self.cursor]
|
ch = self.src[self.cursor]
|
||||||
@ -552,20 +545,21 @@ class QAPISchemaParser(object):
|
|||||||
'For now, \\u escape '
|
'For now, \\u escape '
|
||||||
'only supports non-zero '
|
'only supports non-zero '
|
||||||
'values up to \\u007f')
|
'values up to \\u007f')
|
||||||
string += chr(value)
|
ch = chr(value)
|
||||||
elif ch in '\\/\'"':
|
elif ch not in '\\/\'"':
|
||||||
string += ch
|
|
||||||
else:
|
|
||||||
raise QAPIParseError(self,
|
raise QAPIParseError(self,
|
||||||
"Unknown escape \\%s" % ch)
|
"Unknown escape \\%s" % ch)
|
||||||
esc = False
|
esc = False
|
||||||
elif ch == '\\':
|
elif ch == '\\':
|
||||||
esc = True
|
esc = True
|
||||||
|
continue
|
||||||
elif ch == "'":
|
elif ch == "'":
|
||||||
self.val = string
|
self.val = string
|
||||||
return
|
return
|
||||||
else:
|
if ord(ch) < 32 or ord(ch) >= 127:
|
||||||
string += ch
|
raise QAPIParseError(
|
||||||
|
self, "Funny character in string")
|
||||||
|
string += ch
|
||||||
elif self.src.startswith('true', self.pos):
|
elif self.src.startswith('true', self.pos):
|
||||||
self.val = True
|
self.val = True
|
||||||
self.cursor += 3
|
self.cursor += 3
|
||||||
|
@ -451,6 +451,8 @@ qapi-schema += returns-array-bad.json
|
|||||||
qapi-schema += returns-dict.json
|
qapi-schema += returns-dict.json
|
||||||
qapi-schema += returns-unknown.json
|
qapi-schema += returns-unknown.json
|
||||||
qapi-schema += returns-whitelist.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-deep.json
|
||||||
qapi-schema += struct-base-clash.json
|
qapi-schema += struct-base-clash.json
|
||||||
qapi-schema += struct-data-invalid.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-list.json
|
||||||
qapi-schema += unclosed-object.json
|
qapi-schema += unclosed-object.json
|
||||||
qapi-schema += unclosed-string.json
|
qapi-schema += unclosed-string.json
|
||||||
qapi-schema += unicode-str.json
|
|
||||||
qapi-schema += union-base-empty.json
|
qapi-schema += union-base-empty.json
|
||||||
qapi-schema += union-base-no-discriminator.json
|
qapi-schema += union-base-no-discriminator.json
|
||||||
qapi-schema += union-branch-case.json
|
qapi-schema += union-branch-case.json
|
||||||
|
1
tests/qapi-schema/string-code-point-127.err
Normal file
1
tests/qapi-schema/string-code-point-127.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/string-code-point-127.json:2:14: Funny character in string
|
2
tests/qapi-schema/string-code-point-127.json
Normal file
2
tests/qapi-schema/string-code-point-127.json
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# We accept printable ASCII: code points 32..126. Test code point 127:
|
||||||
|
{ 'command': '' }
|
1
tests/qapi-schema/string-code-point-31.err
Normal file
1
tests/qapi-schema/string-code-point-31.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/string-code-point-31.json:2:14: Funny character in string
|
1
tests/qapi-schema/string-code-point-31.exit
Normal file
1
tests/qapi-schema/string-code-point-31.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
2
tests/qapi-schema/string-code-point-31.json
Normal file
2
tests/qapi-schema/string-code-point-31.json
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# We accept printable ASCII: code points 32..126. Test code point 127:
|
||||||
|
{ 'command': '' }
|
0
tests/qapi-schema/string-code-point-31.out
Normal file
0
tests/qapi-schema/string-code-point-31.out
Normal file
@ -1 +0,0 @@
|
|||||||
tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name 'é'
|
|
@ -1,2 +0,0 @@
|
|||||||
# we don't support full Unicode strings, yet
|
|
||||||
{ 'command': 'é' }
|
|
Loading…
x
Reference in New Issue
Block a user