Skip to content

Commit 5d94c2f

Browse files
committed
gh-151532: Validate xmlrpc.client.dumps arguments without assert
1 parent 11f032f commit 5d94c2f

3 files changed

Lines changed: 58 additions & 3 deletions

File tree

Lib/test/test_xmlrpc.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import contextlib
1717
from test import support
1818
from test.support import os_helper
19+
from test.support import script_helper
1920
from test.support import socket_helper
2021
from test.support import threading_helper
2122
from test.support import ALWAYS_EQ, LARGEST, SMALLEST
@@ -129,6 +130,56 @@ def test_dump_big_long(self):
129130
def test_dump_bad_dict(self):
130131
self.assertRaises(TypeError, xmlrpclib.dumps, ({(1,2,3): 1},))
131132

133+
def test_dump_invalid_params(self):
134+
for params in ([], ["x"], {"x": 1}, "abc", 1):
135+
with self.subTest(params=params):
136+
with self.assertRaisesRegex(
137+
TypeError,
138+
"^argument must be tuple or Fault instance$",
139+
):
140+
xmlrpclib.dumps(params)
141+
142+
def test_dump_invalid_methodresponse(self):
143+
for params in ((), (1, 2)):
144+
with self.subTest(params=params):
145+
with self.assertRaisesRegex(
146+
ValueError,
147+
"^response tuple must be a singleton$",
148+
):
149+
xmlrpclib.dumps(params, methodresponse=True)
150+
151+
def test_dump_invalid_params_optimized(self):
152+
code = r"""
153+
import xmlrpc.client as xmlrpclib
154+
155+
if __debug__:
156+
raise AssertionError("expected optimized mode")
157+
158+
def check(exc_type, message, func):
159+
try:
160+
func()
161+
except exc_type as exc:
162+
if str(exc) != message:
163+
raise AssertionError(str(exc))
164+
else:
165+
raise AssertionError(f"{exc_type.__name__} not raised")
166+
167+
for params in [], ["x"], {"x": 1}, "abc", 1:
168+
check(
169+
TypeError,
170+
"argument must be tuple or Fault instance",
171+
lambda params=params: xmlrpclib.dumps(params),
172+
)
173+
174+
for params in (), (1, 2):
175+
check(
176+
ValueError,
177+
"response tuple must be a singleton",
178+
lambda params=params: xmlrpclib.dumps(params, methodresponse=True),
179+
)
180+
"""
181+
script_helper.assert_python_ok("-O", "-c", code)
182+
132183
def test_dump_recursive_seq(self):
133184
l = [1,2,3]
134185
t = [3,4,5,l]

Lib/xmlrpc/client.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -938,11 +938,12 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None,
938938
where necessary.
939939
"""
940940

941-
assert isinstance(params, (tuple, Fault)), "argument must be tuple or Fault instance"
941+
if not isinstance(params, (tuple, Fault)):
942+
raise TypeError("argument must be tuple or Fault instance")
942943
if isinstance(params, Fault):
943944
methodresponse = 1
944-
elif methodresponse and isinstance(params, tuple):
945-
assert len(params) == 1, "response tuple must be a singleton"
945+
elif methodresponse and len(params) != 1:
946+
raise ValueError("response tuple must be a singleton")
946947

947948
if not encoding:
948949
encoding = "utf-8"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Validate :func:`xmlrpc.client.dumps` arguments with explicit runtime checks
2+
so invalid arguments are rejected consistently when Python runs with
3+
optimization enabled.

0 commit comments

Comments
 (0)