From f85c7dc7e06b9da1c64ae6cc6a6ae810a09dc4f2 Mon Sep 17 00:00:00 2001 From: naweiss Date: Mon, 23 Jun 2025 23:50:22 +0300 Subject: [PATCH 1/8] gh-107545: Fix misleading setsockopt error message --- Modules/socketmodule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index f3ad01854de93b..25e1e465926c5c 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3373,6 +3373,9 @@ sock_setsockopt(PyObject *self, PyObject *args) (char*)&flag, sizeof flag); goto done; } + if (!PyErr_ExceptionMatches(PyExc_TypeError)) { + return NULL; + } PyErr_Clear(); /* setsockopt(level, opt, None, flag) */ @@ -3383,6 +3386,9 @@ sock_setsockopt(PyObject *self, PyObject *args) NULL, (socklen_t)optlen); goto done; } + if (!PyErr_ExceptionMatches(PyExc_TypeError)) { + return NULL; + } PyErr_Clear(); /* setsockopt(level, opt, buffer) */ From 82be24527b8f8485cd0145478ed909829b605554 Mon Sep 17 00:00:00 2001 From: naweiss Date: Tue, 24 Jun 2025 00:03:31 +0300 Subject: [PATCH 2/8] Add tests for setsockopt errors --- Lib/test/test_socket.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 3dd67b2a2aba97..29c979b53a6720 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1538,6 +1538,31 @@ def testSetSockOpt(self): reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) self.assertFalse(reuse == 0, "failed to set reuse mode") + @unittest.skipIf(_testcapi is None, "requires _testcapi") + def test_setsockopt_errors(self): + # See issue #107546. + from _testcapi import INT_MAX, INT_MIN + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.addCleanup(sock.close) + + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # No error expected. + + with self.assertRaises(OverflowError): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MAX + 1) + + with self.assertRaises(OverflowError): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MIN - 1) + + with self.assertRaises(OverflowError): + sock.setsockopt(socket.SOL_SOCKET, INT_MAX + 1, 1) + + with self.assertRaises(OverflowError): + sock.setsockopt(INT_MAX + 1, socket.SO_REUSEADDR, 1) + + with self.assertRaises(TypeError): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict()) + def testSendAfterClose(self): # testing send() after close() with timeout with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: From 167d212bb6a998cd45dfdef174680fa7c152aa22 Mon Sep 17 00:00:00 2001 From: naweiss Date: Tue, 24 Jun 2025 00:11:45 +0300 Subject: [PATCH 3/8] Add issue to news --- .../2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst new file mode 100644 index 00000000000000..3dc853987e0e0b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst @@ -0,0 +1,2 @@ +Improve error message when :meth:`~socket.socket.setsockopt` raises an error +other than a :exc:`TypeError`. From e3d4e7469626f3b0ac1d1ae23024b5205c8be977 Mon Sep 17 00:00:00 2001 From: naweiss Date: Mon, 7 Jul 2025 20:02:50 +0300 Subject: [PATCH 4/8] Cleanup setsockopt implementation --- Lib/test/test_socket.py | 11 +++---- Modules/socketmodule.c | 73 +++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 29c979b53a6720..8b13f6cdc66c74 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1538,27 +1538,24 @@ def testSetSockOpt(self): reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) self.assertFalse(reuse == 0, "failed to set reuse mode") - @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_setsockopt_errors(self): # See issue #107546. - from _testcapi import INT_MAX, INT_MIN - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.addCleanup(sock.close) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # No error expected. with self.assertRaises(OverflowError): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MAX + 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 2 ** 100) with self.assertRaises(OverflowError): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MIN - 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, - 2 ** 100) with self.assertRaises(OverflowError): - sock.setsockopt(socket.SOL_SOCKET, INT_MAX + 1, 1) + sock.setsockopt(socket.SOL_SOCKET, 2 ** 100, 1) with self.assertRaises(OverflowError): - sock.setsockopt(INT_MAX + 1, socket.SO_REUSEADDR, 1) + sock.setsockopt(2 ** 100, socket.SO_REUSEADDR, 1) with self.assertRaises(TypeError): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict()) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 25e1e465926c5c..fa92c144921551 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3338,26 +3338,32 @@ sock_setsockopt(PyObject *self, PyObject *args) Py_buffer optval; int flag; unsigned int optlen; - PyObject *none; + PyObject *type; + + if (!PyArg_ParseTuple(args, "iiO|I:setsockopt", + &level, &optname, &type, &optlen)) { + return NULL; + } #ifdef AF_VSOCK if (s->sock_family == AF_VSOCK) { uint64_t vflag; // Must be set width of 64 bits /* setsockopt(level, opt, flag) */ - if (PyArg_ParseTuple(args, "iiK:setsockopt", - &level, &optname, &vflag)) { - // level should always be set to AF_VSOCK - res = setsockopt(get_sock_fd(s), level, optname, - (void*)&vflag, sizeof vflag); - goto done; + if (!PyArg_Parse(type, "K", &vflag)) { + return NULL; } - return NULL; + // level should always be set to AF_VSOCK + res = setsockopt(get_sock_fd(s), level, optname, + (void*)&vflag, sizeof vflag); + goto done; } #endif /* setsockopt(level, opt, flag) */ - if (PyArg_ParseTuple(args, "iii:setsockopt", - &level, &optname, &flag)) { + if (PyIndex_Check(type)) { + if (!PyArg_Parse(type, "i", &flag)) { + return NULL; + } #ifdef MS_WINDOWS if (optname == SIO_TCP_SET_ACK_FREQUENCY) { DWORD dummy; @@ -3373,43 +3379,40 @@ sock_setsockopt(PyObject *self, PyObject *args) (char*)&flag, sizeof flag); goto done; } - if (!PyErr_ExceptionMatches(PyExc_TypeError)) { - return NULL; - } - PyErr_Clear(); /* setsockopt(level, opt, None, flag) */ - if (PyArg_ParseTuple(args, "iiO!I:setsockopt", - &level, &optname, Py_TYPE(Py_None), &none, &optlen)) { + if (type == Py_None) { assert(sizeof(socklen_t) >= sizeof(unsigned int)); res = setsockopt(get_sock_fd(s), level, optname, NULL, (socklen_t)optlen); goto done; } - if (!PyErr_ExceptionMatches(PyExc_TypeError)) { - return NULL; - } - PyErr_Clear(); /* setsockopt(level, opt, buffer) */ - if (!PyArg_ParseTuple(args, "iiy*:setsockopt", - &level, &optname, &optval)) - return NULL; - + if (PyObject_CheckBuffer(type)) { + if (!PyArg_Parse(type, "y*", &optval)) { + return NULL; + } #ifdef MS_WINDOWS - if (optval.len > INT_MAX) { - PyBuffer_Release(&optval); - PyErr_Format(PyExc_OverflowError, - "socket option is larger than %i bytes", - INT_MAX); - return NULL; - } - res = setsockopt(get_sock_fd(s), level, optname, - optval.buf, (int)optval.len); + if (optval.len > INT_MAX) { + PyBuffer_Release(&optval); + PyErr_Format(PyExc_OverflowError, + "socket option is larger than %i bytes", + INT_MAX); + return NULL; + } + res = setsockopt(get_sock_fd(s), level, optname, + optval.buf, (int)optval.len); #else - res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len); + res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len); #endif - PyBuffer_Release(&optval); + PyBuffer_Release(&optval); + goto done; + } + + PyErr_Format(PyExc_TypeError, + "socket option should be integer, bytes-like object or None"); + return NULL; done: if (res < 0) { From ca87487d4b05077dc3d025922a6249a725a5401c Mon Sep 17 00:00:00 2001 From: naweiss Date: Tue, 8 Jul 2025 11:16:33 +0300 Subject: [PATCH 5/8] Add clearer error messages to setsockopt --- Lib/test/test_socket.py | 15 ++++++++++- Modules/socketmodule.c | 55 +++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 8b13f6cdc66c74..4b85ceb68c18bf 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1557,9 +1557,22 @@ def test_setsockopt_errors(self): with self.assertRaises(OverflowError): sock.setsockopt(2 ** 100, socket.SO_REUSEADDR, 1) - with self.assertRaises(TypeError): + msg = "socket option should be should be integer, bytes-like object or None" + with self.assertRaises(TypeError, msg=msg): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict()) + msg = "setsockopt() takes 3 or 4 arguments (2 given)" + with self.assertRaises(TypeError, msg=msg): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) + + msg = "setsockopt() take 4 arguments when socket option is None (3 given)" + with self.assertRaises(TypeError, msg=msg): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, None) + + msg = "setsockopt() argument 3 must be NoneType, not int" + with self.assertRaises(TypeError, msg=msg): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2) + def testSendAfterClose(self): # testing send() after close() with timeout with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index fa92c144921551..da8d51d46fcf55 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3332,24 +3332,41 @@ sock_setsockopt(PyObject *self, PyObject *args) { PySocketSockObject *s = _PySocketSockObject_CAST(self); + Py_ssize_t arglen; int level; int optname; int res; - Py_buffer optval; + Py_buffer buffer; int flag; unsigned int optlen; - PyObject *type; + PyObject *optval; - if (!PyArg_ParseTuple(args, "iiO|I:setsockopt", - &level, &optname, &type, &optlen)) { - return NULL; + arglen = PyTuple_Size(args); + switch (arglen) { + case 3: + if (!PyArg_ParseTuple(args, "iiO:setsockopt", + &level, &optname, &optval)) { + return NULL; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiO!I:setsockopt", + &level, &optname, Py_TYPE(Py_None), &optval, &optlen)) { + return NULL; + } + break; + default: + PyErr_Format(PyExc_TypeError, + "setsockopt() takes 3 or 4 arguments (%zd given)", + arglen); + return NULL; } #ifdef AF_VSOCK if (s->sock_family == AF_VSOCK) { uint64_t vflag; // Must be set width of 64 bits /* setsockopt(level, opt, flag) */ - if (!PyArg_Parse(type, "K", &vflag)) { + if (!PyArg_Parse(optval, "K", &vflag)) { return NULL; } // level should always be set to AF_VSOCK @@ -3360,8 +3377,8 @@ sock_setsockopt(PyObject *self, PyObject *args) #endif /* setsockopt(level, opt, flag) */ - if (PyIndex_Check(type)) { - if (!PyArg_Parse(type, "i", &flag)) { + if (PyIndex_Check(optval)) { + if (!PyArg_Parse(optval, "i", &flag)) { return NULL; } #ifdef MS_WINDOWS @@ -3381,7 +3398,13 @@ sock_setsockopt(PyObject *self, PyObject *args) } /* setsockopt(level, opt, None, flag) */ - if (type == Py_None) { + if (optval == Py_None) { + if (arglen != 4) { + PyErr_Format(PyExc_TypeError, + "setsockopt() take 4 arguments when socket option is None (%zd given)", + arglen); + return NULL; + } assert(sizeof(socklen_t) >= sizeof(unsigned int)); res = setsockopt(get_sock_fd(s), level, optname, NULL, (socklen_t)optlen); @@ -3389,24 +3412,24 @@ sock_setsockopt(PyObject *self, PyObject *args) } /* setsockopt(level, opt, buffer) */ - if (PyObject_CheckBuffer(type)) { - if (!PyArg_Parse(type, "y*", &optval)) { + if (PyObject_CheckBuffer(optval)) { + if (!PyArg_Parse(optval, "y*", &buffer)) { return NULL; } #ifdef MS_WINDOWS - if (optval.len > INT_MAX) { - PyBuffer_Release(&optval); + if (buffer.len > INT_MAX) { + PyBuffer_Release(&buffer); PyErr_Format(PyExc_OverflowError, "socket option is larger than %i bytes", INT_MAX); return NULL; } res = setsockopt(get_sock_fd(s), level, optname, - optval.buf, (int)optval.len); + buffer.buf, (int)buffer.len); #else - res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len); + res = setsockopt(get_sock_fd(s), level, optname, buffer.buf, buffer.len); #endif - PyBuffer_Release(&optval); + PyBuffer_Release(&buffer); goto done; } From 543c20b34cee2be4f80ea6e31d3e0d27ff9a0b40 Mon Sep 17 00:00:00 2001 From: naweiss Date: Fri, 11 Jul 2025 11:31:28 +0300 Subject: [PATCH 6/8] Simplify error checking implementation for setsockopt --- Lib/test/test_socket.py | 19 ++++++++--------- Modules/socketmodule.c | 47 ++++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 4b85ceb68c18bf..927881b7fa5e7e 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1557,22 +1557,21 @@ def test_setsockopt_errors(self): with self.assertRaises(OverflowError): sock.setsockopt(2 ** 100, socket.SO_REUSEADDR, 1) - msg = "socket option should be should be integer, bytes-like object or None" - with self.assertRaises(TypeError, msg=msg): + with self.assertRaisesRegex(TypeError, "socket option should be int, bytes-like object or None"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict()) - msg = "setsockopt() takes 3 or 4 arguments (2 given)" - with self.assertRaises(TypeError, msg=msg): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) - - msg = "setsockopt() take 4 arguments when socket option is None (3 given)" - with self.assertRaises(TypeError, msg=msg): + with self.assertRaisesRegex(TypeError, "take 4 arguments when socket option is None"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, None) - msg = "setsockopt() argument 3 must be NoneType, not int" - with self.assertRaises(TypeError, msg=msg): + with self.assertRaisesRegex(TypeError, "argument 3 must be NoneType"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2) + with self.assertRaisesRegex(TypeError, "takes at least 3 arguments"): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) + + with self.assertRaisesRegex(TypeError, "takes at most 4 arguments"): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2, 3) + def testSendAfterClose(self): # testing send() after close() with timeout with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index da8d51d46fcf55..555d251b89d72f 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3341,25 +3341,23 @@ sock_setsockopt(PyObject *self, PyObject *args) unsigned int optlen; PyObject *optval; + if (!PyArg_ParseTuple(args, "iiO|I:setsockopt", + &level, &optname, &optval, &optlen)) { + return NULL; + } + arglen = PyTuple_Size(args); - switch (arglen) { - case 3: - if (!PyArg_ParseTuple(args, "iiO:setsockopt", - &level, &optname, &optval)) { - return NULL; - } - break; - case 4: - if (!PyArg_ParseTuple(args, "iiO!I:setsockopt", - &level, &optname, Py_TYPE(Py_None), &optval, &optlen)) { - return NULL; - } - break; - default: - PyErr_Format(PyExc_TypeError, - "setsockopt() takes 3 or 4 arguments (%zd given)", - arglen); - return NULL; + if (arglen == 3 && optval == Py_None) { + PyErr_Format(PyExc_TypeError, + "setsockopt() take 4 arguments when socket option is None (%zd given)", + arglen); + return NULL; + } + if (arglen == 4 && optval != Py_None) { + PyErr_Format(PyExc_TypeError, + "setsockopt() argument 3 must be NoneType, not %s", + Py_TYPE(optval)->tp_name); + return NULL; } #ifdef AF_VSOCK @@ -3397,14 +3395,8 @@ sock_setsockopt(PyObject *self, PyObject *args) goto done; } - /* setsockopt(level, opt, None, flag) */ + /* setsockopt(level, opt, None, optlen) */ if (optval == Py_None) { - if (arglen != 4) { - PyErr_Format(PyExc_TypeError, - "setsockopt() take 4 arguments when socket option is None (%zd given)", - arglen); - return NULL; - } assert(sizeof(socklen_t) >= sizeof(unsigned int)); res = setsockopt(get_sock_fd(s), level, optname, NULL, (socklen_t)optlen); @@ -3425,7 +3417,7 @@ sock_setsockopt(PyObject *self, PyObject *args) return NULL; } res = setsockopt(get_sock_fd(s), level, optname, - buffer.buf, (int)buffer.len); + buffer.buf, (int)buffer.len); #else res = setsockopt(get_sock_fd(s), level, optname, buffer.buf, buffer.len); #endif @@ -3434,7 +3426,8 @@ sock_setsockopt(PyObject *self, PyObject *args) } PyErr_Format(PyExc_TypeError, - "socket option should be integer, bytes-like object or None"); + "socket option should be int, bytes-like object or None (got %s)", + Py_TYPE(optval)->tp_name); return NULL; done: From 2ca926dc2d8789fe0bcd35d886becd7d36f2985b Mon Sep 17 00:00:00 2001 From: naweiss Date: Fri, 11 Jul 2025 12:34:22 +0300 Subject: [PATCH 7/8] Update news entry --- .../2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst | 2 -- .../2025-07-11-12-29-09.gh-issue-107545.ipfl7U.rst | 2 ++ Modules/socketmodule.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-07-11-12-29-09.gh-issue-107545.ipfl7U.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst deleted file mode 100644 index 3dc853987e0e0b..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-24-00-21-27.gh-issue-107545.GDa7Zs.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message when :meth:`~socket.socket.setsockopt` raises an error -other than a :exc:`TypeError`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-07-11-12-29-09.gh-issue-107545.ipfl7U.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-11-12-29-09.gh-issue-107545.ipfl7U.rst new file mode 100644 index 00000000000000..b3ac56a27d942e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-11-12-29-09.gh-issue-107545.ipfl7U.rst @@ -0,0 +1,2 @@ +Improve the error messages that may be raised by +:meth:`~socket.socket.setsockopt` diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 555d251b89d72f..4a3b09f0c21c98 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3355,8 +3355,8 @@ sock_setsockopt(PyObject *self, PyObject *args) } if (arglen == 4 && optval != Py_None) { PyErr_Format(PyExc_TypeError, - "setsockopt() argument 3 must be NoneType, not %s", - Py_TYPE(optval)->tp_name); + "setsockopt() argument 3 must be NoneType, not %T", + optval); return NULL; } @@ -3426,8 +3426,8 @@ sock_setsockopt(PyObject *self, PyObject *args) } PyErr_Format(PyExc_TypeError, - "socket option should be int, bytes-like object or None (got %s)", - Py_TYPE(optval)->tp_name); + "socket option should be int, bytes-like object or None (got %T)", + optval); return NULL; done: From 97ee4dd2158194a6888b3db52a538b5aef0b63cd Mon Sep 17 00:00:00 2001 From: naweiss Date: Tue, 15 Jul 2025 10:58:28 +0300 Subject: [PATCH 8/8] Fix some setsockopt error messages --- Lib/test/test_socket.py | 4 ++-- Modules/socketmodule.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 927881b7fa5e7e..76fd33c7dc8767 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1560,10 +1560,10 @@ def test_setsockopt_errors(self): with self.assertRaisesRegex(TypeError, "socket option should be int, bytes-like object or None"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict()) - with self.assertRaisesRegex(TypeError, "take 4 arguments when socket option is None"): + with self.assertRaisesRegex(TypeError, "requires 4 arguments when the third argument is None"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, None) - with self.assertRaisesRegex(TypeError, "argument 3 must be NoneType"): + with self.assertRaisesRegex(TypeError, "only takes 4 arguments when the third argument is None"): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2) with self.assertRaisesRegex(TypeError, "takes at least 3 arguments"): diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 4a3b09f0c21c98..f3606182193774 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3349,19 +3349,24 @@ sock_setsockopt(PyObject *self, PyObject *args) arglen = PyTuple_Size(args); if (arglen == 3 && optval == Py_None) { PyErr_Format(PyExc_TypeError, - "setsockopt() take 4 arguments when socket option is None (%zd given)", + "setsockopt() requires 4 arguments when the third argument is None", arglen); return NULL; } if (arglen == 4 && optval != Py_None) { PyErr_Format(PyExc_TypeError, - "setsockopt() argument 3 must be NoneType, not %T", + "setsockopt() only takes 4 arguments when the third argument is None (got %T)", optval); return NULL; } #ifdef AF_VSOCK if (s->sock_family == AF_VSOCK) { + if (!PyIndex_Check(optval)) { + PyErr_Format(PyExc_TypeError, + "setsockopt() argument 3 for AF_VSOCK must be an int (got %T)", + optval); + } uint64_t vflag; // Must be set width of 64 bits /* setsockopt(level, opt, flag) */ if (!PyArg_Parse(optval, "K", &vflag)) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy