Title: wrong error messages when using PyArg_ParseTuple to parse normal tuples
Type: behavior Stage: patch review
Components: IO Versions: Python 3.7
Status: open Resolution:
Dependencies: Superseder:
Assigned To: serhiy.storchaka Nosy List: Oren Milman, haypo, rhettinger, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2016-09-23 20:16 by Oren Milman, last changed 2017-03-16 18:30 by Oren Milman.

File name Uploaded Description Edit Oren Milman, 2016-09-23 20:16 an ugly script that verifies the bugs or the patches
issue28261_ver1.diff Oren Milman, 2016-09-23 20:18 proposed patches diff file - ver1 review
patchedCPythonTestOutput_ver1.txt Oren Milman, 2016-09-23 20:18 test output of CPython with my patches (tested on my PC) - ver1
CPythonTestOutput.txt Oren Milman, 2016-09-23 20:19 test output of CPython without my patches (tested on my PC)
Messages (10)
msg277296 - (view) Author: Oren Milman (Oren Milman) * Date: 2016-09-23 20:16
------------ current state ------------
In few places in the codebase, PyArg_ParseTuple is called in order to parse a normal tuple (instead of the usual case of parsing the arguments tuple of a function).
In some of these places, failure of PyArg_ParseTuple is handled simply by cleanup (if needed) and returning an error code, and so an exception with the generic error message is raised.
The generic error message is appropriate in case the parsed tuple is the arguments tuple of a function, but might be really wrong in case it is a normal tuple.

For example, such case in Modules/socketmodule.c in socket_getnameinfo leads to the following:
    >>> import socket
    >>> socket.getnameinfo(tuple(), 1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: function takes at least 2 arguments (0 given)

------------ proposed changes ------------
In each of these places, add to the format string (which is passed to PyArg_ParseTuple) a ';', followed by an appropriate error message, as already done in Modules/audioop.c in audioop_ratecv_impl:
        if (!PyArg_ParseTuple(state,
                        "iO!;audioop.ratecv: illegal state argument",
                        &d, &PyTuple_Type, &samps))
            goto exit;

------------ diff ------------
The proposed patches diff file is attached.

------------ tests ------------
I wrote an ugly script to verify the wrong error messages on CPython without my patches, and to test the patches on CPython with my patches. The script is attached (but it might fail on a non-Windows machine).

In addition, I ran 'python_d.exe -m test -j3' (on my 64-bit Windows 10) with and without the patches, and got quite the same output.
The outputs of both runs are attached.
msg288792 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2017-03-02 10:05
I dislike passing a error message in the function name. I suggest to instead raise a new exception with a better error message and chain it with the previous exception.
msg288861 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-03-03 06:50
Do you mean that in each case PyArg_ParseTuple fails, we should chain
to the exception raised by PyArg_ParseTuple an exception that specifies
the name of the tuple that PyArg_ParseTuple failed to parse, without
specifying the function name?
msg288862 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-03 07:01
An error message is not passed in the function name. PyArg_ParseTuple() allows you to pass an arbitrary error message. I think this feature is specially designed for these cases.

I didn't look the patch close, but Oren's approach LGTM in general.
msg288869 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-03 07:39
Oren, could you write reproducers for all affected cases? I don't think we need to add them as regular tests, but we should be able to check changes manually.

There are conflicts in Modules/itertoolsmodule.c.
msg288911 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-03-03 18:56
-0 The new code looks awful, and in the case of the itertools module, these are messages that users are unlikely to see (the methods are typically only called by pickle, and pickling itself is rare for itertools).
msg288917 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-03 19:18
Would it look less awful if remove "xxxxxx.__setstate__: "?
msg289672 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-03-15 13:00
Raymond? any suggestions for how to make the code less ugly?
or do you have in mind a different approach for solving this issue?
msg289673 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-15 13:06
I suggest to withdraw changes in itertoolsmodule.c and avoid using "dunder" names like __setstate__ and __new__ in error messages.
msg289727 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-03-16 18:30
as Serhiy pointed out in PR 668, here are some more functions that produce the
same kind of wrong error messages:
    - Modules/timemodule.c - gettmarg()
    - Modules/socketmodule.c:
        * getsockaddrarg()
        * socket_getnameinfo()

ISTM that searching for 'PyTuple_Check(' might be a good way to find more such
functions, as they sometimes raise an error in case a type other than tuple was
received (and after that, PyArg_ParseTuple is called).
Date User Action Args
2017-03-16 18:30:12Oren Milmansetmessages: + msg289727
2017-03-15 13:06:57serhiy.storchakasetmessages: + msg289673
2017-03-15 13:00:47Oren Milmansetmessages: + msg289672
2017-03-03 19:18:57serhiy.storchakasetmessages: + msg288917
2017-03-03 18:56:03rhettingersetnosy: + rhettinger
messages: + msg288911
2017-03-03 07:39:11serhiy.storchakasetmessages: + msg288869
2017-03-03 07:01:57serhiy.storchakasetstage: patch review
2017-03-03 07:01:47serhiy.storchakasetassignee: serhiy.storchaka

messages: + msg288862
nosy: + serhiy.storchaka
2017-03-03 06:50:16Oren Milmansetmessages: + msg288861
2017-03-02 10:05:11hayposetnosy: + haypo
messages: + msg288792
2016-09-23 20:19:49Oren Milmansetfiles: + CPythonTestOutput.txt
2016-09-23 20:19:12Oren Milmansetfiles: + patchedCPythonTestOutput_ver1.txt
2016-09-23 20:18:21Oren Milmansetfiles: + issue28261_ver1.diff
keywords: + patch
2016-09-23 20:16:55Oren Milmancreate