Skip to content

Commit cbfaec8

Browse files
committed
Check for excess arguments in PyArg_ParseTuple
1 parent a8fb176 commit cbfaec8

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_method.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
__dir__ = __file__.rpartition("/")[0]
4444

4545

46+
def assert_raises(err, fn, *args, **kwargs):
47+
raised = False
48+
try:
49+
fn(*args, **kwargs)
50+
except err:
51+
raised = True
52+
assert raised
53+
54+
4655
def _reference_classmethod(args):
4756
if isinstance(args[0], type(list.append)):
4857
return classmethod(args[0])()
@@ -103,6 +112,16 @@ def test_methods(self):
103112
assert obj.meth_static_varargs(1, 2, 3) == (None, (1, 2, 3))
104113
assert obj.meth_static_varargs_keywords(1, 2, 3, a=1, b=2) == (None, (1, 2, 3), {'a': 1, 'b': 2})
105114

115+
assert_raises(TypeError, obj.meth_noargs, 1)
116+
assert_raises(TypeError, obj.meth_o)
117+
assert_raises(TypeError, obj.meth_o, 1, 2)
118+
assert_raises(TypeError, obj.meth_class_noargs, 1)
119+
assert_raises(TypeError, obj.meth_class_o)
120+
assert_raises(TypeError, obj.meth_class_o, 1, 2)
121+
assert_raises(TypeError, obj.meth_static_noargs, 1)
122+
assert_raises(TypeError, obj.meth_static_o)
123+
assert_raises(TypeError, obj.meth_static_o, 1, 2)
124+
106125

107126
class TestPyMethod(CPyExtTestCase):
108127
def compile_module(self, name):

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_modsupport.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def _reference_typecheck(args, expected_type):
6363
def _reference_parse_O(args):
6464
if not isinstance(args[0], tuple) or not isinstance(args[1], dict):
6565
raise SystemError
66-
if args[0]:
66+
if len(args[0]) == 1:
6767
return args[0][0]
6868
elif "arg0" in args[1]:
6969
return args[1]["arg0"]
@@ -162,6 +162,7 @@ def compile_module(self, name):
162162
(tuple(), {"arg1": 'helloworld'}),
163163
(1, dict()),
164164
(tuple(), 1),
165+
(("a", "excess"), dict()),
165166
),
166167
code='''
167168
static PyObject* wrap_PyArg_ParseTupleAndKeywords(PyObject* argTuple, PyObject* kwargs) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/common/CExtParseArgumentsNode.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,14 @@ int doSpecial(String funName, PTuple argv, Object kwds, @SuppressWarnings("unuse
155155
@Cached(value = "getChars(format)", allowUncached = true, dimensions = 1) char[] chars,
156156
@Cached("createConvertArgNodes(cachedFormat)") ConvertArgNode[] convertArgNodes,
157157
@Cached HashingCollectionNodes.LenNode kwdsLenNode,
158+
@Cached SequenceStorageNodes.LenNode argvLenNode,
158159
@Cached PRaiseNativeNode raiseNode) {
159160
try {
160161
PDict kwdsDict = null;
161162
if (kwds != null && kwdsLenNode.execute((PDict) kwds) != 0) {
162163
kwdsDict = (PDict) kwds;
163164
}
164-
doParsingExploded(funName, argv, kwdsDict, chars, kwdnames, varargs, nativeConext, convertArgNodes, raiseNode);
165+
doParsingExploded(funName, argv, kwdsDict, chars, kwdnames, varargs, nativeConext, convertArgNodes, argvLenNode, raiseNode);
165166
return 1;
166167
} catch (InteropException | ParseArgumentsException e) {
167168
return 0;
@@ -173,6 +174,7 @@ int doSpecial(String funName, PTuple argv, Object kwds, @SuppressWarnings("unuse
173174
int doGeneric(String funName, PTuple argv, Object kwds, String format, Object kwdnames, Object varargs, CExtContext nativeContext,
174175
@Cached ConvertArgNode convertArgNode,
175176
@Cached HashingCollectionNodes.LenNode kwdsLenNode,
177+
@Cached SequenceStorageNodes.LenNode argvLenNode,
176178
@Cached PRaiseNativeNode raiseNode) {
177179
try {
178180
char[] chars = getChars(format);
@@ -184,12 +186,21 @@ int doGeneric(String funName, PTuple argv, Object kwds, String format, Object kw
184186
for (int i = 0; i < format.length(); i++) {
185187
state = convertArg(state, kwdsDict, chars, i, kwdnames, varargs, convertArgNode, raiseNode);
186188
}
189+
checkExcessArgs(argv, argvLenNode, state, raiseNode);
187190
return 1;
188191
} catch (InteropException | ParseArgumentsException e) {
189192
return 0;
190193
}
191194
}
192195

196+
private static void checkExcessArgs(PTuple argv, SequenceStorageNodes.LenNode argvLenNode, ParserState state, PRaiseNativeNode raiseNode) {
197+
int argvLen = argvLenNode.execute(argv.getSequenceStorage());
198+
if (argvLen > state.v.argnum) {
199+
raiseNode.raiseIntWithoutFrame(0, TypeError, ErrorMessages.EXPECTED_AT_MOST_D_ARGS_GOT_D, state.v.argnum, argvLen);
200+
throw ParseArgumentsException.raise();
201+
}
202+
}
203+
193204
@Fallback
194205
@SuppressWarnings("unused")
195206
int error(String funName, Object argv, Object kwds, Object format, Object kwdnames, Object varargs, CExtContext nativeContext,
@@ -199,13 +210,14 @@ int error(String funName, Object argv, Object kwds, Object format, Object kwdnam
199210

200211
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL_UNTIL_RETURN)
201212
private static void doParsingExploded(String funName, PTuple argv, Object kwds, char[] chars, Object kwdnames, Object varargs, CExtContext nativeContext,
202-
ConvertArgNode[] convertArgNodes, PRaiseNativeNode raiseNode)
213+
ConvertArgNode[] convertArgNodes, SequenceStorageNodes.LenNode argvLenNode, PRaiseNativeNode raiseNode)
203214
throws InteropException, ParseArgumentsException {
204215
CompilerAsserts.partialEvaluationConstant(chars.length);
205216
ParserState state = new ParserState(funName, new PositionalArgStack(argv, null), nativeContext);
206217
for (int i = 0; i < chars.length; i++) {
207218
state = convertArg(state, kwds, chars, i, kwdnames, varargs, convertArgNodes[i], raiseNode);
208219
}
220+
checkExcessArgs(argv, argvLenNode, state, raiseNode);
209221
}
210222

211223
private static ParserState convertArg(ParserState state, Object kwds, char[] format, int format_idx, Object kwdnames, Object varargs, ConvertArgNode convertArgNode,

0 commit comments

Comments
 (0)