@@ -3338,32 +3338,59 @@ sock_setsockopt(PyObject *self, PyObject *args)
33383338{
33393339 PySocketSockObject * s = _PySocketSockObject_CAST (self );
33403340
3341+ Py_ssize_t arglen ;
33413342 int level ;
33423343 int optname ;
33433344 int res ;
3344- Py_buffer optval ;
3345+ Py_buffer buffer ;
33453346 int flag ;
33463347 unsigned int optlen ;
3347- PyObject * none ;
3348+ PyObject * optval ;
3349+
3350+ if (!PyArg_ParseTuple (args , "iiO|I:setsockopt" ,
3351+ & level , & optname , & optval , & optlen ))
3352+ {
3353+ return NULL ;
3354+ }
3355+
3356+ arglen = PyTuple_Size (args );
3357+ if (arglen == 3 && optval == Py_None ) {
3358+ PyErr_Format (PyExc_TypeError ,
3359+ "setsockopt() requires 4 arguments when the third argument is None" ,
3360+ arglen );
3361+ return NULL ;
3362+ }
3363+ if (arglen == 4 && optval != Py_None ) {
3364+ PyErr_Format (PyExc_TypeError ,
3365+ "setsockopt() only takes 4 arguments when the third argument is None (got %T)" ,
3366+ optval );
3367+ return NULL ;
3368+ }
33483369
33493370#ifdef AF_VSOCK
33503371 if (s -> sock_family == AF_VSOCK ) {
3372+ if (!PyIndex_Check (optval )) {
3373+ PyErr_Format (PyExc_TypeError ,
3374+ "setsockopt() argument 3 for AF_VSOCK must be an int (got %T)" ,
3375+ optval );
3376+ }
33513377 uint64_t vflag ; // Must be set width of 64 bits
33523378 /* setsockopt(level, opt, flag) */
3353- if (PyArg_ParseTuple (args , "iiK:setsockopt" ,
3354- & level , & optname , & vflag )) {
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 ;
3379+ if (!PyArg_Parse (optval , "K" , & vflag )) {
3380+ return NULL ;
33593381 }
3360- return NULL ;
3382+ // level should always be set to AF_VSOCK
3383+ res = setsockopt (get_sock_fd (s ), level , optname ,
3384+ (void * )& vflag , sizeof vflag );
3385+ goto done ;
33613386 }
33623387#endif
33633388
33643389 /* setsockopt(level, opt, flag) */
3365- if (PyArg_ParseTuple (args , "iii:setsockopt" ,
3366- & level , & optname , & flag )) {
3390+ if (PyIndex_Check (optval )) {
3391+ if (!PyArg_Parse (optval , "i" , & flag )) {
3392+ return NULL ;
3393+ }
33673394#ifdef MS_WINDOWS
33683395 if (optname == SIO_TCP_SET_ACK_FREQUENCY ) {
33693396 int dummy ;
@@ -3380,36 +3407,40 @@ sock_setsockopt(PyObject *self, PyObject *args)
33803407 goto done ;
33813408 }
33823409
3383- PyErr_Clear ();
3384- /* setsockopt(level, opt, None, flag) */
3385- if (PyArg_ParseTuple (args , "iiO!I:setsockopt" ,
3386- & level , & optname , Py_TYPE (Py_None ), & none , & optlen )) {
3410+ /* setsockopt(level, opt, None, optlen) */
3411+ if (optval == Py_None ) {
33873412 assert (sizeof (socklen_t ) >= sizeof (unsigned int ));
33883413 res = setsockopt (get_sock_fd (s ), level , optname ,
33893414 NULL , (socklen_t )optlen );
33903415 goto done ;
33913416 }
33923417
3393- PyErr_Clear ();
33943418 /* setsockopt(level, opt, buffer) */
3395- if (! PyArg_ParseTuple ( args , "iiy*:setsockopt" ,
3396- & level , & optname , & optval ))
3397- return NULL ;
3398-
3419+ if (PyObject_CheckBuffer ( optval )) {
3420+ if (! PyArg_Parse ( optval , "y*" , & buffer )) {
3421+ return NULL ;
3422+ }
33993423#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 );
3424+ if (buffer .len > INT_MAX ) {
3425+ PyBuffer_Release (& buffer );
3426+ PyErr_Format (PyExc_OverflowError ,
3427+ "socket option is larger than %i bytes" ,
3428+ INT_MAX );
3429+ return NULL ;
3430+ }
3431+ res = setsockopt (get_sock_fd (s ), level , optname ,
3432+ buffer .buf , (int )buffer .len );
34093433#else
3410- res = setsockopt (get_sock_fd (s ), level , optname , optval .buf , optval .len );
3434+ res = setsockopt (get_sock_fd (s ), level , optname , buffer .buf , buffer .len );
34113435#endif
3412- PyBuffer_Release (& optval );
3436+ PyBuffer_Release (& buffer );
3437+ goto done ;
3438+ }
3439+
3440+ PyErr_Format (PyExc_TypeError ,
3441+ "socket option should be int, bytes-like object or None (got %T)" ,
3442+ optval );
3443+ return NULL ;
34133444
34143445done :
34153446 if (res < 0 ) {
0 commit comments