File: | mviewbuf.c |
Warning: | line 238, column 28 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 PyNumber_Long |
2 | PyObject* clang_analyzer_PyObject_New_Reference(); |
3 | PyObject* PyNumber_Long(PyObject *o) { |
4 | return clang_analyzer_PyObject_New_Reference(); |
5 | } |
6 | #else |
7 | #warning "API PyNumber_Long is defined as a macro." |
8 | #endif |