| File: | mviewbuf.c | 
| Warning: | line 356, column 5 PyObject ownership leak with reference count of 1  | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | #include "_pymodule.h" | |||
| 2 | ||||
| 3 | static int get_writable_buffer(PyObject* obj, Py_buffer *buf, int force) | |||
| 4 | { | |||
| 5 | Py_buffer read_buf; | |||
| 6 | int flags = PyBUF_ND0x0008|PyBUF_STRIDES(0x0010 | 0x0008)|PyBUF_FORMAT0x0004; | |||
| 7 | int ret; | |||
| 8 | ||||
| 9 | /* Attempt to get a writable buffer */ | |||
| 10 | if (!PyObject_GetBuffer(obj, buf, flags|PyBUF_WRITABLE0x0001)) | |||
| 11 | return 0; | |||
| 12 | if (!force) | |||
| 13 | return -1; | |||
| 14 | ||||
| 15 | /* Make a writable buffer from a read-only buffer */ | |||
| 16 | PyErr_Clear(); | |||
| 17 | if(-1 == PyObject_GetBuffer(obj, &read_buf, flags)) | |||
| 18 | return -1; | |||
| 19 | ret = PyBuffer_FillInfo(buf, NULL((void*)0), read_buf.buf, read_buf.len, 0, | |||
| 20 | flags|PyBUF_WRITABLE0x0001); | |||
| 21 | PyBuffer_Release(&read_buf); | |||
| 22 | return ret; | |||
| 23 | } | |||
| 24 | ||||
| 25 | static int get_readonly_buffer(PyObject* obj, Py_buffer *buf) | |||
| 26 | { | |||
| 27 | int flags = PyBUF_ND0x0008|PyBUF_STRIDES(0x0010 | 0x0008)|PyBUF_FORMAT0x0004; | |||
| 28 | ||||
| 29 | return PyObject_GetBuffer(obj, buf, flags); | |||
| 30 | } | |||
| 31 | ||||
| 32 | ||||
| 33 | static void free_buffer(Py_buffer * buf) | |||
| 34 | { | |||
| 35 | PyBuffer_Release(buf); | |||
| 36 | } | |||
| 37 | ||||
| 38 | /** | |||
| 39 | * Return a pointer to the data of a writable buffer from obj. If only a | |||
| 40 | * read-only buffer is available and force is True, a read-write buffer based on | |||
| 41 | * the read-only buffer is obtained. Note that this may have some surprising | |||
| 42 | * effects on buffers which expect the data from their read-only buffer not to | |||
| 43 | * be modified. | |||
| 44 | */ | |||
| 45 | static PyObject* | |||
| 46 | memoryview_get_buffer(PyObject *self, PyObject *args){ | |||
| 47 | PyObject *obj = NULL((void*)0); | |||
| 48 | int force = 0; | |||
| 49 | int readonly = 0; | |||
| 50 | PyObject *ret = NULL((void*)0); | |||
| 51 | Py_buffer buf; | |||
| 52 | ||||
| 53 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O|ii", &obj, &force, &readonly)) | |||
| 54 | return NULL((void*)0); | |||
| 55 | ||||
| 56 | if (readonly) { | |||
| 57 | if (get_readonly_buffer(obj, &buf)) | |||
| 58 | return NULL((void*)0); | |||
| 59 | } else { | |||
| 60 | if (get_writable_buffer(obj, &buf, force)) | |||
| 61 | return NULL((void*)0); | |||
| 62 | } | |||
| 63 | ||||
| 64 | ret = PyLong_FromVoidPtr(buf.buf); | |||
| 65 | free_buffer(&buf); | |||
| 66 | return ret; | |||
| 67 | } | |||
| 68 | ||||
| 69 | /** | |||
| 70 | * Gets a half-open range [start, end) which contains the array data | |||
| 71 | * Modified from numpy/core/src/multiarray/array_assign.c | |||
| 72 | */ | |||
| 73 | static PyObject* | |||
| 74 | get_extents(Py_ssize_t *shape, Py_ssize_t *strides, int ndim, | |||
| 75 | Py_ssize_t itemsize, Py_ssize_t ptr) | |||
| 76 | { | |||
| 77 | Py_ssize_t start, end; | |||
| 78 | int idim; | |||
| 79 | Py_ssize_t *dimensions = shape; | |||
| 80 | PyObject *ret = NULL((void*)0); | |||
| 81 | ||||
| 82 | if (ndim < 0 ){ | |||
| 83 | PyErr_SetString(PyExc_ValueError, "buffer ndim < 0"); | |||
| 84 | return NULL((void*)0); | |||
| 85 | } | |||
| 86 | ||||
| 87 | if (!dimensions) { | |||
| 88 | if (ndim == 0) { | |||
| 89 | start = end = ptr; | |||
| 90 | end += itemsize; | |||
| 91 | return Py_BuildValue_Py_BuildValue_SizeT("nn", start, end); | |||
| 92 | } | |||
| 93 | PyErr_SetString(PyExc_ValueError, "buffer shape is not defined"); | |||
| 94 | return NULL((void*)0); | |||
| 95 | } | |||
| 96 | ||||
| 97 | if (!strides) { | |||
| 98 | PyErr_SetString(PyExc_ValueError, "buffer strides is not defined"); | |||
| 99 | return NULL((void*)0); | |||
| 100 | } | |||
| 101 | ||||
| 102 | /* Calculate with a closed range [start, end] */ | |||
| 103 | start = end = ptr; | |||
| 104 | for (idim = 0; idim < ndim; ++idim) { | |||
| 105 | Py_ssize_t stride = strides[idim], dim = dimensions[idim]; | |||
| 106 | /* If the array size is zero, return an empty range */ | |||
| 107 | if (dim == 0) { | |||
| 108 | start = end = ptr; | |||
| 109 | ret = Py_BuildValue_Py_BuildValue_SizeT("nn", start, end); | |||
| 110 | break; | |||
| 111 | } | |||
| 112 | /* Expand either upwards or downwards depending on stride */ | |||
| 113 | else { | |||
| 114 | if (stride > 0) { | |||
| 115 | end += stride * (dim - 1); | |||
| 116 | } | |||
| 117 | else if (stride < 0) { | |||
| 118 | start += stride * (dim - 1); | |||
| 119 | } | |||
| 120 | } | |||
| 121 | } | |||
| 122 | ||||
| 123 | if (!ret) { | |||
| 124 | /* Return a half-open range */ | |||
| 125 | Py_ssize_t out_start = start; | |||
| 126 | Py_ssize_t out_end = end + itemsize; | |||
| 127 | ||||
| 128 | ret = Py_BuildValue_Py_BuildValue_SizeT("nn", out_start, out_end); | |||
| 129 | } | |||
| 130 | ||||
| 131 | return ret; | |||
| 132 | } | |||
| 133 | ||||
| 134 | static PyObject* | |||
| 135 | memoryview_get_extents(PyObject *self, PyObject *args) | |||
| 136 | { | |||
| 137 | PyObject *obj = NULL((void*)0); | |||
| 138 | PyObject *ret = NULL((void*)0); | |||
| 139 | Py_buffer b; | |||
| 140 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O", &obj)) | |||
| 141 | return NULL((void*)0); | |||
| 142 | ||||
| 143 | if (get_readonly_buffer(obj, &b)) | |||
| 144 | return NULL((void*)0); | |||
| 145 | ||||
| 146 | ret = get_extents(b.shape, b.strides, b.ndim, b.itemsize, | |||
| 147 | (Py_ssize_t)b.buf); | |||
| 148 | free_buffer(&b); | |||
| 149 | return ret; | |||
| 150 | } | |||
| 151 | ||||
| 152 | static PyObject* | |||
| 153 | memoryview_get_extents_info(PyObject *self, PyObject *args) | |||
| 154 | { | |||
| 155 | int i; | |||
| 156 | Py_ssize_t *shape_ary = NULL((void*)0); | |||
| 157 | Py_ssize_t *strides_ary = NULL((void*)0); | |||
| 158 | PyObject *shape_tuple = NULL((void*)0); | |||
| 159 | PyObject *strides_tuple = NULL((void*)0); | |||
| 160 | PyObject *shape = NULL((void*)0), *strides = NULL((void*)0); | |||
| 161 | Py_ssize_t itemsize = 0; | |||
| 162 | int ndim = 0; | |||
| 163 | PyObject* res = NULL((void*)0); | |||
| 164 | ||||
| 165 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "OOin", &shape, &strides, &ndim, &itemsize)) | |||
| 166 | goto cleanup; | |||
| 167 | ||||
| 168 | if (ndim < 0) { | |||
| 169 | PyErr_SetString(PyExc_ValueError, "ndim is negative"); | |||
| 170 | goto cleanup; | |||
| 171 | } | |||
| 172 | ||||
| 173 | if (itemsize <= 0) { | |||
| 174 | PyErr_SetString(PyExc_ValueError, "ndim <= 0"); | |||
| 175 | goto cleanup; | |||
| 176 | } | |||
| 177 | ||||
| 178 | shape_ary = malloc(sizeof(Py_ssize_t) * ndim + 1); | |||
| 179 | strides_ary = malloc(sizeof(Py_ssize_t) * ndim + 1); | |||
| 180 | ||||
| 181 | shape_tuple = PySequence_Fast(shape, "shape is not a sequence"); | |||
| 182 | if (!shape_tuple) goto cleanup; | |||
| 183 | ||||
| 184 | for (i = 0; i < ndim; ++i) { | |||
| 185 | shape_ary[i] = PyNumber_AsSsize_t( | |||
| 186 |                            PySequence_Fast_GET_ITEM(shape_tuple, i)(((((((PyObject*)(shape_tuple))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(shape_tuple) )->ob_item[i]) : ((((void) (0)), (PyTupleObject *)(shape_tuple ))->ob_item[i])),  | |||
| 187 | PyExc_OverflowError); | |||
| 188 | } | |||
| 189 | ||||
| 190 | strides_tuple = PySequence_Fast(strides, "strides is not a sequence"); | |||
| 191 | if (!strides_tuple) goto cleanup; | |||
| 192 | ||||
| 193 | for (i = 0; i < ndim; ++i) { | |||
| 194 | strides_ary[i] = PyNumber_AsSsize_t( | |||
| 195 |                            PySequence_Fast_GET_ITEM(strides_tuple, i)(((((((PyObject*)(strides_tuple))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(strides_tuple ))->ob_item[i]) : ((((void) (0)), (PyTupleObject *)(strides_tuple ))->ob_item[i])),  | |||
| 196 | PyExc_OverflowError); | |||
| 197 | } | |||
| 198 | ||||
| 199 | res = get_extents(shape_ary, strides_ary, ndim, itemsize, 0); | |||
| 200 | cleanup: | |||
| 201 | free(shape_ary); | |||
| 202 | free(strides_ary); | |||
| 203 | Py_XDECREF(shape_tuple)_Py_XDECREF(((PyObject*)(shape_tuple))); | |||
| 204 | Py_XDECREF(strides_tuple)_Py_XDECREF(((PyObject*)(strides_tuple))); | |||
| 205 | return res; | |||
| 206 | } | |||
| 207 | ||||
| 208 | ||||
| 209 | /* new type to expose buffer interface */ | |||
| 210 | typedef struct { | |||
| 211 | PyObject_HEADPyObject ob_base; | |||
| 212 | /* Type-specific fields go here. */ | |||
| 213 | } MemAllocObject; | |||
| 214 | ||||
| 215 | ||||
| 216 | static int | |||
| 217 | get_bufinfo(PyObject *self, Py_ssize_t *psize, void **pptr) | |||
| 218 | { | |||
| 219 | PyObject *buflen = NULL((void*)0); | |||
| 220 | PyObject *bufptr = NULL((void*)0); | |||
| 221 | Py_ssize_t size = 0; | |||
| 222 | void* ptr = NULL((void*)0); | |||
| 223 | int ret = -1; | |||
| 224 | ||||
| 225 | buflen = PyObject_GetAttrString(self, "_buflen_"); | |||
| 226 | if (!buflen) goto cleanup; | |||
| 227 | ||||
| 228 | bufptr = PyObject_GetAttrString(self, "_bufptr_"); | |||
| 229 | if (!bufptr) goto cleanup; | |||
| 230 | ||||
| 231 | size = PyNumber_AsSsize_t(buflen, PyExc_OverflowError); | |||
| 232 | if (size == -1 && PyErr_Occurred()) goto cleanup; | |||
| 233 | else if (size < 0) { | |||
| 234 | PyErr_SetString(PyExc_ValueError, "negative buffer size"); | |||
| 235 | goto cleanup; | |||
| 236 | } | |||
| 237 | ||||
| 238 | ptr = PyLong_AsVoidPtr(PyNumber_Long(bufptr)); | |||
| 239 | if (PyErr_Occurred()) | |||
| 240 | goto cleanup; | |||
| 241 | else if (!ptr) { | |||
| 242 | PyErr_SetString(PyExc_ValueError, "null buffer pointer"); | |||
| 243 | goto cleanup; | |||
| 244 | } | |||
| 245 | ||||
| 246 | *psize = size; | |||
| 247 | *pptr = ptr; | |||
| 248 | ret = 0; | |||
| 249 | cleanup: | |||
| 250 | Py_XDECREF(buflen)_Py_XDECREF(((PyObject*)(buflen))); | |||
| 251 | Py_XDECREF(bufptr)_Py_XDECREF(((PyObject*)(bufptr))); | |||
| 252 | return ret; | |||
| 253 | } | |||
| 254 | ||||
| 255 | ||||
| 256 | static int | |||
| 257 | MemAllocObject_getbuffer(PyObject *self, Py_buffer *view, int flags) | |||
| 258 | { | |||
| 259 | Py_ssize_t size = 0; | |||
| 260 | void *ptr = 0; | |||
| 261 | int readonly; | |||
| 262 | ||||
| 263 | if(-1 == get_bufinfo(self, &size, &ptr)) | |||
| 264 | return -1; | |||
| 265 | ||||
| 266 | readonly = (PyBUF_WRITABLE0x0001 & flags) != PyBUF_WRITABLE0x0001; | |||
| 267 | ||||
| 268 | /* fill buffer */ | |||
| 269 | if (-1 == PyBuffer_FillInfo(view, self, (void*)ptr, size, readonly, flags)) | |||
| 270 | return -1; | |||
| 271 | ||||
| 272 | return 0; | |||
| 273 | } | |||
| 274 | ||||
| 275 | static void | |||
| 276 | MemAllocObject_releasebuffer(PyObject *self, Py_buffer *view) | |||
| 277 | { | |||
| 278 | /* Do nothing */ | |||
| 279 | } | |||
| 280 | ||||
| 281 | static PyBufferProcs MemAlloc_as_buffer = { | |||
| 282 | MemAllocObject_getbuffer, | |||
| 283 | MemAllocObject_releasebuffer, | |||
| 284 | }; | |||
| 285 | ||||
| 286 | ||||
| 287 | static PyTypeObject MemAllocType = { | |||
| 288 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
| 289 | "mviewbuf.MemAlloc", /* tp_name */ | |||
| 290 | sizeof(MemAllocObject), /* tp_basicsize */ | |||
| 291 | 0, /* tp_itemsize */ | |||
| 292 | /* methods */ | |||
| 293 | 0, /* tp_dealloc */ | |||
| 294 | 0, /* tp_print */ | |||
| 295 | 0, /* tp_getattr */ | |||
| 296 | 0, /* tp_setattr */ | |||
| 297 | #if PY_MAJOR_VERSION3 >= 3 | |||
| 298 | 0, /* tp_reserved */ | |||
| 299 | #else | |||
| 300 | 0, /* tp_compare */ | |||
| 301 | #endif | |||
| 302 | 0, /*tp_repr*/ | |||
| 303 | 0, /*tp_as_number*/ | |||
| 304 | 0, /*tp_as_sequence*/ | |||
| 305 | 0, /*tp_as_mapping*/ | |||
| 306 | 0, /*tp_hash */ | |||
| 307 | 0, /*tp_call*/ | |||
| 308 | 0, /*tp_str*/ | |||
| 309 | 0, /*tp_getattro*/ | |||
| 310 | 0, /*tp_setattro*/ | |||
| 311 | &MemAlloc_as_buffer, /*tp_as_buffer*/ | |||
| 312 | (Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0)| Py_TPFLAGS_BASETYPE(1UL << 10)), /* tp_flags */ | |||
| 313 | 0, /* tp_doc */ | |||
| 314 | ||||
| 315 | 0, /* tp_traverse */ | |||
| 316 | 0, /* tp_clear */ | |||
| 317 | 0, /* tp_richcompare */ | |||
| 318 | 0, /* tp_weaklistoffset */ | |||
| 319 | 0, /* tp_iter */ | |||
| 320 | 0, /* tp_iternext */ | |||
| 321 | 0, /* tp_methods */ | |||
| 322 | 0, /* tp_members */ | |||
| 323 | 0, /* tp_getset */ | |||
| 324 | 0, /* tp_base */ | |||
| 325 | 0, /* tp_dict */ | |||
| 326 | 0, /* tp_descr_get */ | |||
| 327 | 0, /* tp_descr_set */ | |||
| 328 | 0, /* tp_dictoffset */ | |||
| 329 | 0, /* tp_init */ | |||
| 330 | 0, /* tp_alloc */ | |||
| 331 | 0, /* tp_new */ | |||
| 332 | 0, /* tp_free */ | |||
| 333 | 0, /* tp_is_gc */ | |||
| 334 | 0, /* tp_bases */ | |||
| 335 | 0, /* tp_mro */ | |||
| 336 | 0, /* tp_cache */ | |||
| 337 | 0, /* tp_subclasses */ | |||
| 338 | 0, /* tp_weaklist */ | |||
| 339 | 0, /* tp_del */ | |||
| 340 | 0, /* tp_version_tag */ | |||
| 341 | }; | |||
| 342 | ||||
| 343 | ||||
| 344 | static PyMethodDef core_methods[] = { | |||
| 345 | #define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS0x0001 , NULL((void*)0) } | |||
| 346 | declmethod(memoryview_get_buffer), | |||
| 347 | declmethod(memoryview_get_extents), | |||
| 348 | declmethod(memoryview_get_extents_info), | |||
| 349 | { NULL((void*)0) }, | |||
| 350 | #undef declmethod | |||
| 351 | }; | |||
| 352 | ||||
| 353 | ||||
| 354 | MOD_INIT(mviewbuf)PyObject* PyInit_mviewbuf(void) { | |||
| 355 | PyObject *module; | |||
| 356 |     MOD_DEF(module, "mviewbuf", "No docs", core_methods){ static struct PyModuleDef moduledef = { { { 1, ((void*)0) } , ((void*)0), 0, ((void*)0), }, "mviewbuf", "No docs", -1, core_methods , ((void*)0), ((void*)0), ((void*)0), ((void*)0) }; module = PyModule_Create2 (&moduledef, 1013); }  | |||
  | ||||
  | ||||
| 357 | if (module == NULL((void*)0)) | |||
| 358 | return MOD_ERROR_VAL((void*)0); | |||
| 359 | ||||
| 360 | MemAllocType.tp_new = PyType_GenericNew; | |||
| 361 | if (PyType_Ready(&MemAllocType) < 0){ | |||
| 362 | return MOD_ERROR_VAL((void*)0); | |||
| 363 | } | |||
| 364 | ||||
| 365 | Py_INCREF(&MemAllocType)_Py_INCREF(((PyObject*)(&MemAllocType))); | |||
| 366 | PyModule_AddObject(module, "MemAlloc", (PyObject*)&MemAllocType); | |||
| 367 | ||||
| 368 | return MOD_SUCCESS_VAL(module)module; | |||
| 369 | } | |||
| 370 | 
| 1 | #ifndef PyModule_Create2 | 
| 2 | PyObject* clang_analyzer_PyObject_New_Reference(); | 
| 3 | PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) { | 
| 4 | return clang_analyzer_PyObject_New_Reference(); | 
| 5 | } | 
| 6 | #else | 
| 7 | #warning "API PyModule_Create2 is defined as a macro." | 
| 8 | #endif |