summaryrefslogtreecommitdiffstats
path: root/Objects/abstract.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r--Objects/abstract.c260
1 files changed, 147 insertions, 113 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 124e766..5e96138 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -64,49 +64,72 @@ PyObject_Length(PyObject *o)
}
#define PyObject_Length PyObject_Size
+int
+_PyObject_HasLen(PyObject *o) {
+ return (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_length) ||
+ (Py_TYPE(o)->tp_as_mapping && Py_TYPE(o)->tp_as_mapping->mp_length);
+}
/* The length hint function returns a non-negative value from o.__len__()
- or o.__length_hint__(). If those methods aren't found or return a negative
- value, then the defaultvalue is returned. If one of the calls fails,
+ or o.__length_hint__(). If those methods aren't found the defaultvalue is
+ returned. If one of the calls fails with an exception other than TypeError
this function returns -1.
*/
Py_ssize_t
-_PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
+PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
{
+ PyObject *hint, *result;
+ Py_ssize_t res;
_Py_IDENTIFIER(__length_hint__);
- PyObject *ro, *hintmeth;
- Py_ssize_t rv;
-
- /* try o.__len__() */
- rv = PyObject_Size(o);
- if (rv >= 0)
- return rv;
- if (PyErr_Occurred()) {
- if (!PyErr_ExceptionMatches(PyExc_TypeError))
- return -1;
- PyErr_Clear();
+ if (_PyObject_HasLen(o)) {
+ res = PyObject_Length(o);
+ if (res < 0 && PyErr_Occurred()) {
+ if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
+ return -1;
+ }
+ PyErr_Clear();
+ }
+ else {
+ return res;
+ }
}
-
- /* try o.__length_hint__() */
- hintmeth = _PyObject_LookupSpecial(o, &PyId___length_hint__);
- if (hintmeth == NULL) {
- if (PyErr_Occurred())
+ hint = _PyObject_LookupSpecial(o, &PyId___length_hint__);
+ if (hint == NULL) {
+ if (PyErr_Occurred()) {
return -1;
- else
+ }
+ return defaultvalue;
+ }
+ result = PyObject_CallFunctionObjArgs(hint, NULL);
+ Py_DECREF(hint);
+ if (result == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+ PyErr_Clear();
return defaultvalue;
+ }
+ return -1;
}
- ro = PyObject_CallFunctionObjArgs(hintmeth, NULL);
- Py_DECREF(hintmeth);
- if (ro == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_TypeError))
- return -1;
- PyErr_Clear();
+ else if (result == Py_NotImplemented) {
+ Py_DECREF(result);
return defaultvalue;
}
- rv = PyLong_Check(ro) ? PyLong_AsSsize_t(ro) : defaultvalue;
- Py_DECREF(ro);
- return rv;
+ if (!PyLong_Check(result)) {
+ PyErr_Format(PyExc_TypeError, "__length_hint__ must be an integer, not %.100s",
+ Py_TYPE(result)->tp_name);
+ Py_DECREF(result);
+ return -1;
+ }
+ res = PyLong_AsSsize_t(result);
+ Py_DECREF(result);
+ if (res < 0 && PyErr_Occurred()) {
+ return -1;
+ }
+ if (res < 0) {
+ PyErr_Format(PyExc_ValueError, "__length_hint__() should return >= 0");
+ return -1;
+ }
+ return res;
}
PyObject *
@@ -202,7 +225,7 @@ PyObject_DelItem(PyObject *o, PyObject *key)
}
int
-PyObject_DelItemString(PyObject *o, char *key)
+PyObject_DelItemString(PyObject *o, const char *key)
{
PyObject *okey;
int ret;
@@ -227,28 +250,7 @@ PyObject_AsCharBuffer(PyObject *obj,
const char **buffer,
Py_ssize_t *buffer_len)
{
- PyBufferProcs *pb;
- Py_buffer view;
-
- if (obj == NULL || buffer == NULL || buffer_len == NULL) {
- null_error();
- return -1;
- }
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL || pb->bf_getbuffer == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected bytes, bytearray "
- "or buffer compatible object");
- return -1;
- }
- if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
-
- *buffer = view.buf;
- *buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
- return 0;
+ return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len);
}
int
@@ -272,28 +274,18 @@ int PyObject_AsReadBuffer(PyObject *obj,
const void **buffer,
Py_ssize_t *buffer_len)
{
- PyBufferProcs *pb;
Py_buffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
return -1;
}
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getbuffer == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected an object with a buffer interface");
+ if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
return -1;
- }
-
- if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
*buffer = view.buf;
*buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
+ PyBuffer_Release(&view);
return 0;
}
@@ -319,9 +311,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
*buffer = view.buf;
*buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
+ PyBuffer_Release(&view);
return 0;
}
@@ -330,13 +320,15 @@ int PyObject_AsWriteBuffer(PyObject *obj,
int
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
{
- if (!PyObject_CheckBuffer(obj)) {
+ PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
+
+ if (pb == NULL || pb->bf_getbuffer == NULL) {
PyErr_Format(PyExc_TypeError,
"'%.100s' does not support the buffer interface",
Py_TYPE(obj)->tp_name);
return -1;
}
- return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+ return (*pb->bf_getbuffer)(obj, view, flags);
}
static int
@@ -465,7 +457,7 @@ PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
/* Otherwise a more elaborate scheme is needed */
- /* XXX(nnorwitz): need to check for overflow! */
+ /* view->ndim <= 64 */
indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim));
if (indices == NULL) {
PyErr_NoMemory();
@@ -487,10 +479,10 @@ PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
*/
elements = len / view->itemsize;
while (elements--) {
- addone(view->ndim, indices, view->shape);
ptr = PyBuffer_GetPointer(view, indices);
memcpy(ptr, src, view->itemsize);
src += view->itemsize;
+ addone(view->ndim, indices, view->shape);
}
PyMem_Free(indices);
@@ -629,10 +621,14 @@ void
PyBuffer_Release(Py_buffer *view)
{
PyObject *obj = view->obj;
- if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
- Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
- Py_XDECREF(obj);
+ PyBufferProcs *pb;
+ if (obj == NULL)
+ return;
+ pb = Py_TYPE(obj)->tp_as_buffer;
+ if (pb && pb->bf_releasebuffer)
+ pb->bf_releasebuffer(obj, view);
view->obj = NULL;
+ Py_DECREF(obj);
}
PyObject *
@@ -1162,6 +1158,15 @@ PyNumber_Index(PyObject *item)
Py_DECREF(result);
return NULL;
}
+ /* Issue #17576: warn if 'result' not of exact type int. */
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "__index__ returned non-int (type %.200s). "
+ "The ability to return an instance of a strict subclass of int "
+ "is deprecated, and may be removed in a future version of Python.",
+ result->ob_type->tp_name)) {
+ Py_DECREF(result);
+ return NULL;
+ }
return result;
}
@@ -1217,8 +1222,7 @@ PyNumber_Long(PyObject *o)
{
PyNumberMethods *m;
PyObject *trunc_func;
- const char *buffer;
- Py_ssize_t buffer_len;
+ Py_buffer view;
_Py_IDENTIFIER(__trunc__);
if (o == NULL)
@@ -1239,7 +1243,7 @@ PyNumber_Long(PyObject *o)
if (truncated == NULL || PyLong_Check(truncated))
return truncated;
/* __trunc__ is specified to return an Integral type,
- but int() needs to return a int. */
+ but int() needs to return an int. */
m = truncated->ob_type->tp_as_number;
if (m == NULL || m->nb_int == NULL) {
PyErr_Format(
@@ -1256,6 +1260,10 @@ PyNumber_Long(PyObject *o)
if (PyErr_Occurred())
return NULL;
+ if (PyUnicode_Check(o))
+ /* The below check is done in PyLong_FromUnicode(). */
+ return PyLong_FromUnicodeObject(o, 10);
+
if (PyBytes_Check(o))
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular int('9\x005') must raise an
@@ -1263,14 +1271,29 @@ PyNumber_Long(PyObject *o)
*/
return _PyLong_FromBytes(PyBytes_AS_STRING(o),
PyBytes_GET_SIZE(o), 10);
- if (PyUnicode_Check(o))
- /* The above check is done in PyLong_FromUnicode(). */
- return PyLong_FromUnicodeObject(o, 10);
- if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
- return _PyLong_FromBytes(buffer, buffer_len, 10);
- return type_error("int() argument must be a string or a "
- "number, not '%.200s'", o);
+ if (PyByteArray_Check(o))
+ return _PyLong_FromBytes(PyByteArray_AS_STRING(o),
+ PyByteArray_GET_SIZE(o), 10);
+
+ if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) {
+ PyObject *result, *bytes;
+
+ /* Copy to NUL-terminated buffer. */
+ bytes = PyBytes_FromStringAndSize((const char *)view.buf, view.len);
+ if (bytes == NULL) {
+ PyBuffer_Release(&view);
+ return NULL;
+ }
+ result = _PyLong_FromBytes(PyBytes_AS_STRING(bytes),
+ PyBytes_GET_SIZE(bytes), 10);
+ Py_DECREF(bytes);
+ PyBuffer_Release(&view);
+ return result;
+ }
+
+ return type_error("int() argument must be a string, a bytes-like object "
+ "or a number, not '%.200s'", o);
}
PyObject *
@@ -1631,7 +1654,7 @@ PySequence_Tuple(PyObject *v)
Py_INCREF(v);
return v;
}
- if (PyList_Check(v))
+ if (PyList_CheckExact(v))
return PyList_AsTuple(v);
/* Get iterator. */
@@ -1640,7 +1663,7 @@ PySequence_Tuple(PyObject *v)
return NULL;
/* Guess result size and allocate space. */
- n = _PyObject_LengthHint(v, 10);
+ n = PyObject_LengthHint(v, 10);
if (n == -1)
goto Fail;
result = PyTuple_New(n);
@@ -1900,7 +1923,7 @@ PyMapping_Length(PyObject *o)
#define PyMapping_Length PyMapping_Size
PyObject *
-PyMapping_GetItemString(PyObject *o, char *key)
+PyMapping_GetItemString(PyObject *o, const char *key)
{
PyObject *okey, *r;
@@ -1916,7 +1939,7 @@ PyMapping_GetItemString(PyObject *o, char *key)
}
int
-PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
+PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value)
{
PyObject *okey;
int r;
@@ -1935,7 +1958,7 @@ PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
}
int
-PyMapping_HasKeyString(PyObject *o, char *key)
+PyMapping_HasKeyString(PyObject *o, const char *key)
{
PyObject *v;
@@ -2034,10 +2057,16 @@ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
return NULL;
result = (*call)(func, arg, kw);
Py_LeaveRecursiveCall();
- if (result == NULL && !PyErr_Occurred())
+#ifdef NDEBUG
+ if (result == NULL && !PyErr_Occurred()) {
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
+ }
+#else
+ assert((result != NULL && !PyErr_Occurred())
+ || (result == NULL && PyErr_Occurred()));
+#endif
return result;
}
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
@@ -2072,7 +2101,7 @@ call_function_tail(PyObject *callable, PyObject *args)
}
PyObject *
-PyObject_CallFunction(PyObject *callable, char *format, ...)
+PyObject_CallFunction(PyObject *callable, const char *format, ...)
{
va_list va;
PyObject *args;
@@ -2087,12 +2116,14 @@ PyObject_CallFunction(PyObject *callable, char *format, ...)
}
else
args = PyTuple_New(0);
+ if (args == NULL)
+ return NULL;
return call_function_tail(callable, args);
}
PyObject *
-_PyObject_CallFunction_SizeT(PyObject *callable, char *format, ...)
+_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
{
va_list va;
PyObject *args;
@@ -2112,7 +2143,7 @@ _PyObject_CallFunction_SizeT(PyObject *callable, char *format, ...)
}
static PyObject*
-callmethod(PyObject* func, char *format, va_list va, int is_size_t)
+callmethod(PyObject* func, const char *format, va_list va, int is_size_t)
{
PyObject *retval = NULL;
PyObject *args;
@@ -2141,7 +2172,7 @@ callmethod(PyObject* func, char *format, va_list va, int is_size_t)
}
PyObject *
-PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
+PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
{
va_list va;
PyObject *func = NULL;
@@ -2151,9 +2182,8 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
return null_error();
func = PyObject_GetAttrString(o, name);
- if (func == NULL) {
- return 0;
- }
+ if (func == NULL)
+ return NULL;
va_start(va, format);
retval = callmethod(func, format, va, 0);
@@ -2162,7 +2192,8 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
}
PyObject *
-_PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, char *format, ...)
+_PyObject_CallMethodId(PyObject *o, _Py_Identifier *name,
+ const char *format, ...)
{
va_list va;
PyObject *func = NULL;
@@ -2172,9 +2203,8 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, char *format, ...)
return null_error();
func = _PyObject_GetAttrId(o, name);
- if (func == NULL) {
- return 0;
- }
+ if (func == NULL)
+ return NULL;
va_start(va, format);
retval = callmethod(func, format, va, 0);
@@ -2183,7 +2213,8 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, char *format, ...)
}
PyObject *
-_PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)
+_PyObject_CallMethod_SizeT(PyObject *o, const char *name,
+ const char *format, ...)
{
va_list va;
PyObject *func = NULL;
@@ -2193,9 +2224,8 @@ _PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)
return null_error();
func = PyObject_GetAttrString(o, name);
- if (func == NULL) {
- return 0;
- }
+ if (func == NULL)
+ return NULL;
va_start(va, format);
retval = callmethod(func, format, va, 1);
va_end(va);
@@ -2203,7 +2233,8 @@ _PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)
}
PyObject *
-_PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name, char *format, ...)
+_PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
+ const char *format, ...)
{
va_list va;
PyObject *func = NULL;
@@ -2273,7 +2304,7 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
}
PyObject *
-_PyObject_CallMethodObjIdArgs(PyObject *callable,
+_PyObject_CallMethodIdObjArgs(PyObject *callable,
struct _Py_Identifier *name, ...)
{
PyObject *args, *tmp;
@@ -2648,8 +2679,8 @@ PyIter_Next(PyObject *iter)
* NULL terminated string pointers with a NULL char* terminating the array.
* (ie: an argv or env list)
*
- * Memory allocated for the returned list is allocated using malloc() and MUST
- * be freed by the caller using a free() loop or _Py_FreeCharPArray().
+ * Memory allocated for the returned list is allocated using PyMem_Malloc()
+ * and MUST be freed by _Py_FreeCharPArray().
*/
char *const *
_PySequence_BytesToCharpArray(PyObject* self)
@@ -2657,6 +2688,7 @@ _PySequence_BytesToCharpArray(PyObject* self)
char **array;
Py_ssize_t i, argc;
PyObject *item = NULL;
+ Py_ssize_t size;
argc = PySequence_Size(self);
if (argc == -1)
@@ -2669,7 +2701,7 @@ _PySequence_BytesToCharpArray(PyObject* self)
return NULL;
}
- array = malloc((argc + 1) * sizeof(char *));
+ array = PyMem_Malloc((argc + 1) * sizeof(char *));
if (array == NULL) {
PyErr_NoMemory();
return NULL;
@@ -2688,11 +2720,13 @@ _PySequence_BytesToCharpArray(PyObject* self)
array[i] = NULL;
goto fail;
}
- array[i] = strdup(data);
+ size = PyBytes_GET_SIZE(item) + 1;
+ array[i] = PyMem_Malloc(size);
if (!array[i]) {
PyErr_NoMemory();
goto fail;
}
+ memcpy(array[i], data, size);
Py_DECREF(item);
}
array[argc] = NULL;
@@ -2712,7 +2746,7 @@ _Py_FreeCharPArray(char *const array[])
{
Py_ssize_t i;
for (i = 0; array[i] != NULL; ++i) {
- free(array[i]);
+ PyMem_Free(array[i]);
}
- free((void*)array);
+ PyMem_Free((void*)array);
}