@@ -3332,32 +3332,59 @@ sock_setsockopt(PyObject *self, PyObject *args)
3332
3332
{
3333
3333
PySocketSockObject * s = _PySocketSockObject_CAST (self );
3334
3334
3335
+ Py_ssize_t arglen ;
3335
3336
int level ;
3336
3337
int optname ;
3337
3338
int res ;
3338
- Py_buffer optval ;
3339
+ Py_buffer buffer ;
3339
3340
int flag ;
3340
3341
unsigned int optlen ;
3341
- PyObject * none ;
3342
+ PyObject * optval ;
3343
+
3344
+ if (!PyArg_ParseTuple (args , "iiO|I:setsockopt" ,
3345
+ & level , & optname , & optval , & optlen ))
3346
+ {
3347
+ return NULL ;
3348
+ }
3349
+
3350
+ arglen = PyTuple_Size (args );
3351
+ if (arglen == 3 && optval == Py_None ) {
3352
+ PyErr_Format (PyExc_TypeError ,
3353
+ "setsockopt() requires 4 arguments when the third argument is None" ,
3354
+ arglen );
3355
+ return NULL ;
3356
+ }
3357
+ if (arglen == 4 && optval != Py_None ) {
3358
+ PyErr_Format (PyExc_TypeError ,
3359
+ "setsockopt() only takes 4 arguments when the third argument is None (got %T)" ,
3360
+ optval );
3361
+ return NULL ;
3362
+ }
3342
3363
3343
3364
#ifdef AF_VSOCK
3344
3365
if (s -> sock_family == AF_VSOCK ) {
3366
+ if (!PyIndex_Check (optval )) {
3367
+ PyErr_Format (PyExc_TypeError ,
3368
+ "setsockopt() argument 3 for AF_VSOCK must be an int (got %T)" ,
3369
+ optval );
3370
+ }
3345
3371
uint64_t vflag ; // Must be set width of 64 bits
3346
3372
/* 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 ;
3373
+ if (!PyArg_Parse (optval , "K" , & vflag )) {
3374
+ return NULL ;
3353
3375
}
3354
- return NULL ;
3376
+ // level should always be set to AF_VSOCK
3377
+ res = setsockopt (get_sock_fd (s ), level , optname ,
3378
+ (void * )& vflag , sizeof vflag );
3379
+ goto done ;
3355
3380
}
3356
3381
#endif
3357
3382
3358
3383
/* setsockopt(level, opt, flag) */
3359
- if (PyArg_ParseTuple (args , "iii:setsockopt" ,
3360
- & level , & optname , & flag )) {
3384
+ if (PyIndex_Check (optval )) {
3385
+ if (!PyArg_Parse (optval , "i" , & flag )) {
3386
+ return NULL ;
3387
+ }
3361
3388
#ifdef MS_WINDOWS
3362
3389
if (optname == SIO_TCP_SET_ACK_FREQUENCY ) {
3363
3390
DWORD dummy ;
@@ -3374,36 +3401,40 @@ sock_setsockopt(PyObject *self, PyObject *args)
3374
3401
goto done ;
3375
3402
}
3376
3403
3377
- PyErr_Clear ();
3378
- /* setsockopt(level, opt, None, flag) */
3379
- if (PyArg_ParseTuple (args , "iiO!I:setsockopt" ,
3380
- & level , & optname , Py_TYPE (Py_None ), & none , & optlen )) {
3404
+ /* setsockopt(level, opt, None, optlen) */
3405
+ if (optval == Py_None ) {
3381
3406
assert (sizeof (socklen_t ) >= sizeof (unsigned int ));
3382
3407
res = setsockopt (get_sock_fd (s ), level , optname ,
3383
3408
NULL , (socklen_t )optlen );
3384
3409
goto done ;
3385
3410
}
3386
3411
3387
- PyErr_Clear ();
3388
3412
/* setsockopt(level, opt, buffer) */
3389
- if (! PyArg_ParseTuple ( args , "iiy*:setsockopt" ,
3390
- & level , & optname , & optval ))
3391
- return NULL ;
3392
-
3413
+ if (PyObject_CheckBuffer ( optval )) {
3414
+ if (! PyArg_Parse ( optval , "y*" , & buffer )) {
3415
+ return NULL ;
3416
+ }
3393
3417
#ifdef MS_WINDOWS
3394
- if (optval .len > INT_MAX ) {
3395
- PyBuffer_Release (& optval );
3396
- PyErr_Format (PyExc_OverflowError ,
3397
- "socket option is larger than %i bytes" ,
3398
- INT_MAX );
3399
- return NULL ;
3400
- }
3401
- res = setsockopt (get_sock_fd (s ), level , optname ,
3402
- optval .buf , (int )optval .len );
3418
+ if (buffer .len > INT_MAX ) {
3419
+ PyBuffer_Release (& buffer );
3420
+ PyErr_Format (PyExc_OverflowError ,
3421
+ "socket option is larger than %i bytes" ,
3422
+ INT_MAX );
3423
+ return NULL ;
3424
+ }
3425
+ res = setsockopt (get_sock_fd (s ), level , optname ,
3426
+ buffer .buf , (int )buffer .len );
3403
3427
#else
3404
- res = setsockopt (get_sock_fd (s ), level , optname , optval .buf , optval .len );
3428
+ res = setsockopt (get_sock_fd (s ), level , optname , buffer .buf , buffer .len );
3405
3429
#endif
3406
- PyBuffer_Release (& optval );
3430
+ PyBuffer_Release (& buffer );
3431
+ goto done ;
3432
+ }
3433
+
3434
+ PyErr_Format (PyExc_TypeError ,
3435
+ "socket option should be int, bytes-like object or None (got %T)" ,
3436
+ optval );
3437
+ return NULL ;
3407
3438
3408
3439
done :
3409
3440
if (res < 0 ) {
0 commit comments