Skip to content

Commit 277202c

Browse files
authored
Xmlrpc: accept data:str|bytes and require method:str (#12734)
Declared <https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py#L622> Inside [`do_POST()`](https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py#L493) `data: bytes`, where `decode_request_content()` only handles `gzip` compression. The `result` is then written to `self.wfile`, which uses `bytes`. But for [CGI](https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py#L636) `str` is used: [`handle_xmlrpc(self, request_text)`](https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py#L642) calls the argument `request_text`, which is read from `sys.stdin` as type `str` and then passed to `_marshaled_dispatch()`, which internally calls [`xmlrpc.client.loads()`](https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py#L257) to parse the XML using Expat, which accepts both `str` and `bytes`; the later defaults to encoding `utf-8`, but other encodings can be used when explicitly specified: >>> xmlrpc.client.loads('<params><param><value><string>ä</string></value></param></params>') (('ä',), None) >>> xmlrpc.client.loads('<params><param><value><string>ä</string></value></param></params>'.encode("utf-8")) (('ä',), None) >>> xmlrpc.client.loads('<params><param><value><string>ä</string></value></param></params>'.encode("iso-8859-1")) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.11/xmlrpc/client.py", line 1029, in loads p.feed(data) File "/usr/lib/python3.11/xmlrpc/client.py", line 451, in feed self._parser.Parse(data, False) xml.parsers.expat.ExpatError: not well-formed (invalid token): line 3, column 15 >>> xmlrpc.client.loads('<?xml version="1.0" encoding="utf-8"?><params><param><value><string>ä</string></value></param></params>'.encode("iso-8859-1")) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.11/xmlrpc/client.py", line 1029, in loads p.feed(data) File "/usr/lib/python3.11/xmlrpc/client.py", line 451, in feed self._parser.Parse(data, False) xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 68 >>> xmlrpc.client.loads('<?xml version="1.0" encoding="iso-8859-1"?><params><param><value><string>ä</string></value></param></params>'.encode("iso-8859-1")) (('ä',), None) Signed-off-by: Philipp Hahn <hahn@univention.de> Reviewed-By: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent d16fe74 commit 277202c

2 files changed

Lines changed: 4 additions & 3 deletions

File tree

stdlib/xmlrpc/client.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def dumps(
200200
allow_none: bool = False,
201201
) -> str: ...
202202
def loads(
203-
data: str, use_datetime: bool = False, use_builtin_types: bool = False
203+
data: str | ReadableBuffer, use_datetime: bool = False, use_builtin_types: bool = False
204204
) -> tuple[tuple[_Marshallable, ...], str | None]: ...
205205
def gzip_encode(data: ReadableBuffer) -> bytes: ... # undocumented
206206
def gzip_decode(data: ReadableBuffer, max_decode: int = 20971520) -> bytes: ... # undocumented

stdlib/xmlrpc/server.pyi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import http.server
22
import pydoc
33
import socketserver
4+
from _typeshed import ReadableBuffer
45
from collections.abc import Callable, Iterable, Mapping
56
from re import Pattern
67
from typing import Any, ClassVar, Protocol
@@ -48,8 +49,8 @@ class SimpleXMLRPCDispatcher: # undocumented
4849
def register_multicall_functions(self) -> None: ...
4950
def _marshaled_dispatch(
5051
self,
51-
data: str,
52-
dispatch_method: Callable[[str | None, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = None,
52+
data: str | ReadableBuffer,
53+
dispatch_method: Callable[[str, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = None,
5354
path: Any | None = None,
5455
) -> str: ... # undocumented
5556
def system_listMethods(self) -> list[str]: ... # undocumented

0 commit comments

Comments
 (0)