Skip to content

Commit dc9ee63

Browse files
committed
[GR-24538] Raise TypeError on missing argument in PyArg_ParseTuple*
PullRequest: graalpython/1337
2 parents a27b05f + 1abe818 commit dc9ee63

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ def _reference_typecheck(args, expected_type):
5454
return args[0][0]
5555

5656

57+
def _reference_parse_O(args):
58+
assert isinstance(args[0], tuple)
59+
assert isinstance(args[1], dict)
60+
if args[0]:
61+
return args[0][0]
62+
elif "arg0" in args[1]:
63+
return args[1]["arg0"]
64+
raise TypeError
65+
66+
5767
class Indexable:
5868
def __int__(self):
5969
return 456
@@ -107,6 +117,32 @@ def compile_module(self, name):
107117
cmpfunc=unhandled_error_compare
108118
)
109119

120+
test_parseargs_O = CPyExtFunction(
121+
_reference_parse_O,
122+
lambda: (
123+
(('helloworld', ), dict()),
124+
(tuple(), {"arg0": 'helloworld'}),
125+
(tuple(), dict()),
126+
(tuple(), {"arg1": 'helloworld'}),
127+
),
128+
code='''
129+
static PyObject* wrap_PyArg_ParseTupleAndKeywords(PyObject* argTuple, PyObject* kwargs) {
130+
PyObject* out = NULL;
131+
static char *kwdnames[] = {"arg0", NULL};
132+
if (PyArg_ParseTupleAndKeywords(argTuple, kwargs, "O", kwdnames, &out) == 0) {
133+
return NULL;
134+
}
135+
Py_XINCREF(out);
136+
return out;
137+
}
138+
''',
139+
resultspec="O",
140+
argspec="OO",
141+
arguments=["PyObject* argTuple", "PyObject* kwargs"],
142+
callfunction="wrap_PyArg_ParseTupleAndKeywords",
143+
cmpfunc=unhandled_error_compare
144+
)
145+
110146
test_parseargs_O_conv = CPyExtFunction(
111147
lambda args: True if args[0][0] else False,
112148
lambda: (

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,14 +1021,19 @@ abstract static class GetArgNode extends Node {
10211021
static Object doNoKeywords(ParserState state, Object kwds, Object kwdnames, boolean keywordsOnly,
10221022
@Shared("lenNode") @Cached SequenceNodes.LenNode lenNode,
10231023
@Shared("getSequenceStorageNode") @Cached GetSequenceStorageNode getSequenceStorageNode,
1024-
@Shared("getItemNode") @Cached SequenceStorageNodes.GetItemDynamicNode getItemNode) {
1024+
@Shared("getItemNode") @Cached SequenceStorageNodes.GetItemDynamicNode getItemNode,
1025+
@Shared("raiseNode") @Cached PRaiseNativeNode raiseNode) {
10251026

10261027
Object out = null;
10271028
assert !keywordsOnly;
10281029
int l = lenNode.execute(state.v.argv);
10291030
if (state.v.argnum < l) {
10301031
out = getItemNode.execute(getSequenceStorageNode.execute(state.v.argv), state.v.argnum);
10311032
}
1033+
if (out == null && !state.restOptional) {
1034+
raiseNode.raiseIntWithoutFrame(0, TypeError, "%s missing required argument (pos %d)", state.funName, state.v.argnum);
1035+
throw ParseArgumentsException.raise();
1036+
}
10321037
state.v.argnum++;
10331038
return out;
10341039
}
@@ -1041,7 +1046,8 @@ static Object doGeneric(ParserState state, Object kwds, Object kwdnames, boolean
10411046
@Cached HashingCollectionNodes.GetDictStorageNode getDictStorageNode,
10421047
@CachedLibrary(limit = "1") InteropLibrary kwdnamesLib,
10431048
@CachedLibrary(limit = "1") HashingStorageLibrary lib,
1044-
@Cached PCallCExtFunction callCStringToString) throws InteropException {
1049+
@Cached PCallCExtFunction callCStringToString,
1050+
@Shared("raiseNode") @Cached PRaiseNativeNode raiseNode) throws InteropException {
10451051

10461052
Object out = null;
10471053
if (!keywordsOnly) {
@@ -1062,6 +1068,10 @@ static Object doGeneric(ParserState state, Object kwds, Object kwdnames, boolean
10621068
out = lib.getItem(getDictStorageNode.execute((PDict) kwds), kwdname);
10631069
}
10641070
}
1071+
if (out == null && !state.restOptional) {
1072+
raiseNode.raiseIntWithoutFrame(0, TypeError, "%s missing required argument (pos %d)", state.funName, state.v.argnum);
1073+
throw ParseArgumentsException.raise();
1074+
}
10651075
state.v.argnum++;
10661076
return out;
10671077
}

0 commit comments

Comments
 (0)