Skip to content

Commit

Permalink
Xmlrpc: accept data:str|bytes and require method:str (python#12734)
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-By: Jelle Zijlstra <[email protected]>
  • Loading branch information
pmhahn authored Oct 4, 2024
1 parent d16fe74 commit 277202c
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 3 deletions.
2 changes: 1 addition & 1 deletion stdlib/xmlrpc/client.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def dumps(
allow_none: bool = False,
) -> str: ...
def loads(
data: str, use_datetime: bool = False, use_builtin_types: bool = False
data: str | ReadableBuffer, use_datetime: bool = False, use_builtin_types: bool = False
) -> tuple[tuple[_Marshallable, ...], str | None]: ...
def gzip_encode(data: ReadableBuffer) -> bytes: ... # undocumented
def gzip_decode(data: ReadableBuffer, max_decode: int = 20971520) -> bytes: ... # undocumented
Expand Down
5 changes: 3 additions & 2 deletions stdlib/xmlrpc/server.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import http.server
import pydoc
import socketserver
from _typeshed import ReadableBuffer
from collections.abc import Callable, Iterable, Mapping
from re import Pattern
from typing import Any, ClassVar, Protocol
Expand Down Expand Up @@ -48,8 +49,8 @@ class SimpleXMLRPCDispatcher: # undocumented
def register_multicall_functions(self) -> None: ...
def _marshaled_dispatch(
self,
data: str,
dispatch_method: Callable[[str | None, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = None,
data: str | ReadableBuffer,
dispatch_method: Callable[[str, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = None,
path: Any | None = None,
) -> str: ... # undocumented
def system_listMethods(self) -> list[str]: ... # undocumented
Expand Down

0 comments on commit 277202c

Please sign in to comment.