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