From eb6f8de8bf105b4d6e9e21898e76c5647a48a3c9 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Thu, 31 Dec 2009 03:56:09 +0000 Subject: Issue #6687: Moved the special-case for integers out of PyBytes_FromObject. --- Doc/c-api/object.rst | 9 +++++---- Misc/NEWS | 3 +++ Objects/bytesobject.c | 46 +++++++++++++++++++++++++--------------------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index b0700a1..a7be156 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -142,10 +142,11 @@ Object Protocol .. index:: builtin: bytes - Compute a bytes representation of object *o*. *NULL* is returned on failure - and a bytes object on success. This is equivalent to the Python expression - ``bytes(o)``. - + Compute a bytes representation of object *o*. *NULL* is returned on + failure and a bytes object on success. This is equivalent to the Python + expression ``bytes(o)``, when *o* is not an integer. Unlike ``bytes(o)``, + a TypeError is raised when *o* is an integer instead of a zero-initialized + bytes object. .. cfunction:: int PyObject_IsInstance(PyObject *inst, PyObject *cls) diff --git a/Misc/NEWS b/Misc/NEWS index 64319f0..ba555ee 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -140,6 +140,9 @@ Core and Builtins - Issue #4856: Remove checks for win NT. +- Issue #6687: PyBytes_FromObject() no longer accepts an integer as its + argument to construct a null-initialized bytes object. + C-API ----- diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 41eee40..cb63448 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2884,6 +2884,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) const char *encoding = NULL; const char *errors = NULL; PyObject *new = NULL; + Py_ssize_t size; static char *kwlist[] = {"source", "encoding", "errors", 0}; if (type != &PyBytes_Type) @@ -2914,6 +2915,25 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) assert(PyBytes_Check(new)); return new; } + /* Is it an integer? */ + size = PyNumber_AsSsize_t(x, PyExc_ValueError); + if (size == -1 && PyErr_Occurred()) { + PyErr_Clear(); + } + else { + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "negative count"); + return NULL; + } + new = PyBytes_FromStringAndSize(NULL, size); + if (new == NULL) { + return NULL; + } + if (size > 0) { + memset(((PyBytesObject*)new)->ob_sval, 0, size); + } + return new; + } /* If it's not unicode, there can't be encoding or errors */ if (encoding != NULL || errors != NULL) { @@ -2934,27 +2954,6 @@ PyBytes_FromObject(PyObject *x) PyErr_BadInternalCall(); return NULL; } - - /* Is it an int? */ - size = PyNumber_AsSsize_t(x, PyExc_ValueError); - if (size == -1 && PyErr_Occurred()) { - PyErr_Clear(); - } - else { - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative count"); - return NULL; - } - new = PyBytes_FromStringAndSize(NULL, size); - if (new == NULL) { - return NULL; - } - if (size > 0) { - memset(((PyBytesObject*)new)->ob_sval, 0, size); - } - return new; - } - /* Use the modern buffer interface */ if (PyObject_CheckBuffer(x)) { Py_buffer view; @@ -2974,6 +2973,11 @@ PyBytes_FromObject(PyObject *x) PyBuffer_Release(&view); return NULL; } + if (PyUnicode_Check(x)) { + PyErr_SetString(PyExc_TypeError, + "cannot convert unicode object to bytes"); + return NULL; + } /* For iterator version, create a string object and resize as needed */ /* XXX(gb): is 64 a good value? also, optimize if length is known */ -- cgit v0.12