Skip to content

Commit e3d4e74

Browse files
committed
Cleanup setsockopt implementation
1 parent 167d212 commit e3d4e74

File tree

2 files changed

+42
-42
lines changed

2 files changed

+42
-42
lines changed

Lib/test/test_socket.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,27 +1538,24 @@ def testSetSockOpt(self):
15381538
reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
15391539
self.assertFalse(reuse == 0, "failed to set reuse mode")
15401540

1541-
@unittest.skipIf(_testcapi is None, "requires _testcapi")
15421541
def test_setsockopt_errors(self):
15431542
# See issue #107546.
1544-
from _testcapi import INT_MAX, INT_MIN
1545-
15461543
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15471544
self.addCleanup(sock.close)
15481545

15491546
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # No error expected.
15501547

15511548
with self.assertRaises(OverflowError):
1552-
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MAX + 1)
1549+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 2 ** 100)
15531550

15541551
with self.assertRaises(OverflowError):
1555-
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, INT_MIN - 1)
1552+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, - 2 ** 100)
15561553

15571554
with self.assertRaises(OverflowError):
1558-
sock.setsockopt(socket.SOL_SOCKET, INT_MAX + 1, 1)
1555+
sock.setsockopt(socket.SOL_SOCKET, 2 ** 100, 1)
15591556

15601557
with self.assertRaises(OverflowError):
1561-
sock.setsockopt(INT_MAX + 1, socket.SO_REUSEADDR, 1)
1558+
sock.setsockopt(2 ** 100, socket.SO_REUSEADDR, 1)
15621559

15631560
with self.assertRaises(TypeError):
15641561
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict())

Modules/socketmodule.c

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3338,26 +3338,32 @@ sock_setsockopt(PyObject *self, PyObject *args)
33383338
Py_buffer optval;
33393339
int flag;
33403340
unsigned int optlen;
3341-
PyObject *none;
3341+
PyObject *type;
3342+
3343+
if (!PyArg_ParseTuple(args, "iiO|I:setsockopt",
3344+
&level, &optname, &type, &optlen)) {
3345+
return NULL;
3346+
}
33423347

33433348
#ifdef AF_VSOCK
33443349
if (s->sock_family == AF_VSOCK) {
33453350
uint64_t vflag; // Must be set width of 64 bits
33463351
/* setsockopt(level, opt, flag) */
3347-
if (PyArg_ParseTuple(args, "iiK:setsockopt",
3348-
&level, &optname, &vflag)) {
3349-
// level should always be set to AF_VSOCK
3350-
res = setsockopt(get_sock_fd(s), level, optname,
3351-
(void*)&vflag, sizeof vflag);
3352-
goto done;
3352+
if (!PyArg_Parse(type, "K", &vflag)) {
3353+
return NULL;
33533354
}
3354-
return NULL;
3355+
// level should always be set to AF_VSOCK
3356+
res = setsockopt(get_sock_fd(s), level, optname,
3357+
(void*)&vflag, sizeof vflag);
3358+
goto done;
33553359
}
33563360
#endif
33573361

33583362
/* setsockopt(level, opt, flag) */
3359-
if (PyArg_ParseTuple(args, "iii:setsockopt",
3360-
&level, &optname, &flag)) {
3363+
if (PyIndex_Check(type)) {
3364+
if (!PyArg_Parse(type, "i", &flag)) {
3365+
return NULL;
3366+
}
33613367
#ifdef MS_WINDOWS
33623368
if (optname == SIO_TCP_SET_ACK_FREQUENCY) {
33633369
DWORD dummy;
@@ -3373,43 +3379,40 @@ sock_setsockopt(PyObject *self, PyObject *args)
33733379
(char*)&flag, sizeof flag);
33743380
goto done;
33753381
}
3376-
if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
3377-
return NULL;
3378-
}
33793382

3380-
PyErr_Clear();
33813383
/* setsockopt(level, opt, None, flag) */
3382-
if (PyArg_ParseTuple(args, "iiO!I:setsockopt",
3383-
&level, &optname, Py_TYPE(Py_None), &none, &optlen)) {
3384+
if (type == Py_None) {
33843385
assert(sizeof(socklen_t) >= sizeof(unsigned int));
33853386
res = setsockopt(get_sock_fd(s), level, optname,
33863387
NULL, (socklen_t)optlen);
33873388
goto done;
33883389
}
3389-
if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
3390-
return NULL;
3391-
}
33923390

3393-
PyErr_Clear();
33943391
/* setsockopt(level, opt, buffer) */
3395-
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
3396-
&level, &optname, &optval))
3397-
return NULL;
3398-
3392+
if (PyObject_CheckBuffer(type)) {
3393+
if (!PyArg_Parse(type, "y*", &optval)) {
3394+
return NULL;
3395+
}
33993396
#ifdef MS_WINDOWS
3400-
if (optval.len > INT_MAX) {
3401-
PyBuffer_Release(&optval);
3402-
PyErr_Format(PyExc_OverflowError,
3403-
"socket option is larger than %i bytes",
3404-
INT_MAX);
3405-
return NULL;
3406-
}
3407-
res = setsockopt(get_sock_fd(s), level, optname,
3408-
optval.buf, (int)optval.len);
3397+
if (optval.len > INT_MAX) {
3398+
PyBuffer_Release(&optval);
3399+
PyErr_Format(PyExc_OverflowError,
3400+
"socket option is larger than %i bytes",
3401+
INT_MAX);
3402+
return NULL;
3403+
}
3404+
res = setsockopt(get_sock_fd(s), level, optname,
3405+
optval.buf, (int)optval.len);
34093406
#else
3410-
res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len);
3407+
res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len);
34113408
#endif
3412-
PyBuffer_Release(&optval);
3409+
PyBuffer_Release(&optval);
3410+
goto done;
3411+
}
3412+
3413+
PyErr_Format(PyExc_TypeError,
3414+
"socket option should be integer, bytes-like object or None");
3415+
return NULL;
34133416

34143417
done:
34153418
if (res < 0) {

0 commit comments

Comments
 (0)