@@ -3332,24 +3332,41 @@ 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 * type ;
3342+ PyObject * optval ;
33423343
3343- if (!PyArg_ParseTuple (args , "iiO|I:setsockopt" ,
3344- & level , & optname , & type , & optlen )) {
3345- return NULL ;
3344+ arglen = PyTuple_Size (args );
3345+ switch (arglen ) {
3346+ case 3 :
3347+ if (!PyArg_ParseTuple (args , "iiO:setsockopt" ,
3348+ & level , & optname , & optval )) {
3349+ return NULL ;
3350+ }
3351+ break ;
3352+ case 4 :
3353+ if (!PyArg_ParseTuple (args , "iiO!I:setsockopt" ,
3354+ & level , & optname , Py_TYPE (Py_None ), & optval , & optlen )) {
3355+ return NULL ;
3356+ }
3357+ break ;
3358+ default :
3359+ PyErr_Format (PyExc_TypeError ,
3360+ "setsockopt() takes 3 or 4 arguments (%zd given)" ,
3361+ arglen );
3362+ return NULL ;
33463363 }
33473364
33483365#ifdef AF_VSOCK
33493366 if (s -> sock_family == AF_VSOCK ) {
33503367 uint64_t vflag ; // Must be set width of 64 bits
33513368 /* setsockopt(level, opt, flag) */
3352- if (!PyArg_Parse (type , "K" , & vflag )) {
3369+ if (!PyArg_Parse (optval , "K" , & vflag )) {
33533370 return NULL ;
33543371 }
33553372 // level should always be set to AF_VSOCK
@@ -3360,8 +3377,8 @@ sock_setsockopt(PyObject *self, PyObject *args)
33603377#endif
33613378
33623379 /* setsockopt(level, opt, flag) */
3363- if (PyIndex_Check (type )) {
3364- if (!PyArg_Parse (type , "i" , & flag )) {
3380+ if (PyIndex_Check (optval )) {
3381+ if (!PyArg_Parse (optval , "i" , & flag )) {
33653382 return NULL ;
33663383 }
33673384#ifdef MS_WINDOWS
@@ -3381,32 +3398,38 @@ sock_setsockopt(PyObject *self, PyObject *args)
33813398 }
33823399
33833400 /* setsockopt(level, opt, None, flag) */
3384- if (type == Py_None ) {
3401+ if (optval == Py_None ) {
3402+ if (arglen != 4 ) {
3403+ PyErr_Format (PyExc_TypeError ,
3404+ "setsockopt() take 4 arguments when socket option is None (%zd given)" ,
3405+ arglen );
3406+ return NULL ;
3407+ }
33853408 assert (sizeof (socklen_t ) >= sizeof (unsigned int ));
33863409 res = setsockopt (get_sock_fd (s ), level , optname ,
33873410 NULL , (socklen_t )optlen );
33883411 goto done ;
33893412 }
33903413
33913414 /* setsockopt(level, opt, buffer) */
3392- if (PyObject_CheckBuffer (type )) {
3393- if (!PyArg_Parse (type , "y*" , & optval )) {
3415+ if (PyObject_CheckBuffer (optval )) {
3416+ if (!PyArg_Parse (optval , "y*" , & buffer )) {
33943417 return NULL ;
33953418 }
33963419#ifdef MS_WINDOWS
3397- if (optval .len > INT_MAX ) {
3398- PyBuffer_Release (& optval );
3420+ if (buffer .len > INT_MAX ) {
3421+ PyBuffer_Release (& buffer );
33993422 PyErr_Format (PyExc_OverflowError ,
34003423 "socket option is larger than %i bytes" ,
34013424 INT_MAX );
34023425 return NULL ;
34033426 }
34043427 res = setsockopt (get_sock_fd (s ), level , optname ,
3405- optval .buf , (int )optval .len );
3428+ buffer .buf , (int )buffer .len );
34063429#else
3407- res = setsockopt (get_sock_fd (s ), level , optname , optval .buf , optval .len );
3430+ res = setsockopt (get_sock_fd (s ), level , optname , buffer .buf , buffer .len );
34083431#endif
3409- PyBuffer_Release (& optval );
3432+ PyBuffer_Release (& buffer );
34103433 goto done ;
34113434 }
34123435
0 commit comments