@@ -3332,32 +3332,59 @@ sock_setsockopt(PyObject *self, PyObject *args)
33323332{
33333333 PySocketSockObject * s = _PySocketSockObject_CAST (self );
33343334
3335+ Py_ssize_t arglen ;
33353336 int level ;
33363337 int optname ;
33373338 int res ;
3338- Py_buffer optval ;
3339+ Py_buffer buffer ;
33393340 int flag ;
33403341 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+ }
33423363
33433364#ifdef AF_VSOCK
33443365 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+ }
33453371 uint64_t vflag ; // Must be set width of 64 bits
33463372 /* 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 ;
33533375 }
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 ;
33553380 }
33563381#endif
33573382
33583383 /* 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+ }
33613388#ifdef MS_WINDOWS
33623389 if (optname == SIO_TCP_SET_ACK_FREQUENCY ) {
33633390 DWORD dummy ;
@@ -3374,36 +3401,40 @@ sock_setsockopt(PyObject *self, PyObject *args)
33743401 goto done ;
33753402 }
33763403
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 ) {
33813406 assert (sizeof (socklen_t ) >= sizeof (unsigned int ));
33823407 res = setsockopt (get_sock_fd (s ), level , optname ,
33833408 NULL , (socklen_t )optlen );
33843409 goto done ;
33853410 }
33863411
3387- PyErr_Clear ();
33883412 /* 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+ }
33933417#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 );
34033427#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 );
34053429#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 ;
34073438
34083439done :
34093440 if (res < 0 ) {
0 commit comments