diff options
Diffstat (limited to 'Modules/socketmodule.c')
| -rw-r--r-- | Modules/socketmodule.c | 148 | 
1 files changed, 96 insertions, 52 deletions
| diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 8f571a2eb4..ec35fb9533 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -926,7 +926,7 @@ static PyThread_type_lock netdb_lock;     an error occurred; then an exception is raised. */  static int -setipaddr(char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int af) +setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int af)  {      struct addrinfo hints, *res;      int error; @@ -1107,7 +1107,7 @@ makeipaddr(struct sockaddr *addr, int addrlen)     an error occurred. */  static int -setbdaddr(char *name, bdaddr_t *bdaddr) +setbdaddr(const char *name, bdaddr_t *bdaddr)  {      unsigned int b0, b1, b2, b3, b4, b5;      char ch; @@ -1401,7 +1401,7 @@ static int  idna_converter(PyObject *obj, struct maybe_idna *data)  {      size_t len; -    PyObject *obj2, *obj3; +    PyObject *obj2;      if (obj == NULL) {          idna_cleanup(data);          return 1; @@ -1416,31 +1416,27 @@ idna_converter(PyObject *obj, struct maybe_idna *data)          data->buf = PyByteArray_AsString(obj);          len = PyByteArray_Size(obj);      } -    else if (PyUnicode_Check(obj) && PyUnicode_READY(obj) == 0 && PyUnicode_IS_COMPACT_ASCII(obj)) { -        data->buf = PyUnicode_DATA(obj); -        len = PyUnicode_GET_LENGTH(obj); -    } -    else { -        obj2 = PyUnicode_FromObject(obj); -        if (!obj2) { -            PyErr_Format(PyExc_TypeError, "string or unicode text buffer expected, not %s", -                         obj->ob_type->tp_name); -            return 0; +    else if (PyUnicode_Check(obj)) { +        if (PyUnicode_READY(obj) == 0 && PyUnicode_IS_COMPACT_ASCII(obj)) { +            data->buf = PyUnicode_DATA(obj); +            len = PyUnicode_GET_LENGTH(obj);          } -        obj3 = PyUnicode_AsEncodedString(obj2, "idna", NULL); -        Py_DECREF(obj2); -        if (!obj3) { -            PyErr_SetString(PyExc_TypeError, "encoding of hostname failed"); -            return 0; -        } -        if (!PyBytes_Check(obj3)) { -            Py_DECREF(obj3); -            PyErr_SetString(PyExc_TypeError, "encoding of hostname failed to return bytes"); -            return 0; +        else { +            obj2 = PyUnicode_AsEncodedString(obj, "idna", NULL); +            if (!obj2) { +                PyErr_SetString(PyExc_TypeError, "encoding of hostname failed"); +                return 0; +            } +            assert(PyBytes_Check(obj2)); +            data->obj = obj2; +            data->buf = PyBytes_AS_STRING(obj2); +            len = PyBytes_GET_SIZE(obj2);          } -        data->obj = obj3; -        data->buf = PyBytes_AS_STRING(obj3); -        len = PyBytes_GET_SIZE(obj3); +    } +    else { +        PyErr_Format(PyExc_TypeError, "str, bytes or bytearray expected, not %s", +                     obj->ob_type->tp_name); +        return 0;      }      if (strlen(data->buf) != len) {          Py_CLEAR(data->obj); @@ -2458,13 +2454,26 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)          if (!PyArg_ParseTuple(args, "iiy*:setsockopt",                                &level, &optname, &optval))              return NULL; +#ifdef MS_WINDOWS +        if (optval.len > INT_MAX) { +            PyBuffer_Release(&optval); +            PyErr_Format(PyExc_OverflowError, +                         "socket option is larger than %i bytes", +                         INT_MAX); +            return NULL; +        } +        res = setsockopt(s->sock_fd, level, optname, +                         optval.buf, (int)optval.len); +#else          res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len); +#endif          PyBuffer_Release(&optval);      } -    if (res < 0) +    if (res < 0) {          return s->errorhandler(); -    Py_INCREF(Py_None); -    return Py_None; +    } + +    Py_RETURN_NONE;  }  PyDoc_STRVAR(setsockopt_doc, @@ -2563,16 +2572,22 @@ static PyObject *  sock_close(PySocketSockObject *s)  {      SOCKET_T fd; +    int res; -    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ -     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html -     * for more details. -     */ -    if ((fd = s->sock_fd) != -1) { +    fd = s->sock_fd; +    if (fd != -1) {          s->sock_fd = -1; + +        /* We do not want to retry upon EINTR: see +           http://lwn.net/Articles/576478/ and +           http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html +           for more details. */          Py_BEGIN_ALLOW_THREADS -        (void) SOCKETCLOSE(fd); +        res = SOCKETCLOSE(fd);          Py_END_ALLOW_THREADS +        if (res < 0) { +            return s->errorhandler(); +        }      }      Py_INCREF(Py_None);      return Py_None; @@ -4163,22 +4178,45 @@ static PyGetSetDef sock_getsetlist[] = {     First close the file description. */  static void -sock_dealloc(PySocketSockObject *s) +sock_finalize(PySocketSockObject *s)  { +    SOCKET_T fd; +    PyObject *error_type, *error_value, *error_traceback; + +    /* Save the current exception, if any. */ +    PyErr_Fetch(&error_type, &error_value, &error_traceback); +      if (s->sock_fd != -1) { -        PyObject *exc, *val, *tb; -        Py_ssize_t old_refcount = Py_REFCNT(s); -        ++Py_REFCNT(s); -        PyErr_Fetch(&exc, &val, &tb); -        if (PyErr_WarnFormat(PyExc_ResourceWarning, 1, -                             "unclosed %R", s)) +        if (PyErr_ResourceWarning((PyObject *)s, 1, "unclosed %R", s)) {              /* Spurious errors can appear at shutdown */ -            if (PyErr_ExceptionMatches(PyExc_Warning)) -                PyErr_WriteUnraisable((PyObject *) s); -        PyErr_Restore(exc, val, tb); -        (void) SOCKETCLOSE(s->sock_fd); -        Py_REFCNT(s) = old_refcount; +            if (PyErr_ExceptionMatches(PyExc_Warning)) { +                PyErr_WriteUnraisable((PyObject *)s); +            } +        } + +        /* Only close the socket *after* logging the ResourceWarning warning +           to allow the logger to call socket methods like +           socket.getsockname(). If the socket is closed before, socket +           methods fails with the EBADF error. */ +        fd = s->sock_fd; +        s->sock_fd = -1; + +        /* We do not want to retry upon EINTR: see sock_close() */ +        Py_BEGIN_ALLOW_THREADS +        (void) SOCKETCLOSE(fd); +        Py_END_ALLOW_THREADS      } + +    /* Restore the saved exception. */ +    PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +sock_dealloc(PySocketSockObject *s) +{ +    if (PyObject_CallFinalizerFromDealloc((PyObject *)s) < 0) +        return; +      Py_TYPE(s)->tp_free((PyObject *)s);  } @@ -4395,7 +4433,8 @@ static PyTypeObject sock_type = {      PyObject_GenericGetAttr,                    /* tp_getattro */      0,                                          /* tp_setattro */      0,                                          /* tp_as_buffer */ -    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ +    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE +        | Py_TPFLAGS_HAVE_FINALIZE,             /* tp_flags */      sock_doc,                                   /* tp_doc */      0,                                          /* tp_traverse */      0,                                          /* tp_clear */ @@ -4415,6 +4454,15 @@ static PyTypeObject sock_type = {      PyType_GenericAlloc,                        /* tp_alloc */      sock_new,                                   /* tp_new */      PyObject_Del,                               /* tp_free */ +    0,                                          /* tp_is_gc */ +    0,                                          /* tp_bases */ +    0,                                          /* tp_mro */ +    0,                                          /* tp_cache */ +    0,                                          /* tp_subclasses */ +    0,                                          /* tp_weaklist */ +    0,                                          /* tp_del */ +    0,                                          /* tp_version_tag */ +    (destructor)sock_finalize,                  /* tp_finalize */  }; @@ -5450,10 +5498,6 @@ socket_inet_ntop(PyObject *self, PyObject *args)      } else {          return PyUnicode_FromString(retval);      } - -    /* NOTREACHED */ -    PyErr_SetString(PyExc_RuntimeError, "invalid handling of inet_ntop"); -    return NULL;  }  #elif defined(MS_WINDOWS) | 
