Bug Summary

File:mviewbuf.c
Warning:line 238, column 28
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mviewbuf.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/numba/csa-scan,ctu-index-name=/tmp/pyrefcon/numba/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/numba/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/numba -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -D NDEBUG -D _FORTIFY_SOURCE=2 -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wsign-compare -Wall -Wformat -Werror=format-security -Wformat -Werror=format-security -Wdate-time -fdebug-compilation-dir=/tmp/pyrefcon/numba -ferror-limit 19 -fwrapv -pthread -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/numba/csa-scan/reports -x c numba/mviewbuf.c

numba/mviewbuf.c

1#include "_pymodule.h"
2
3static 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
25static 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
33static 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 */
45static PyObject*
46memoryview_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 */
73static PyObject*
74get_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
134static PyObject*
135memoryview_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
152static PyObject*
153memoryview_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);
200cleanup:
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 */
210typedef struct {
211 PyObject_HEADPyObject ob_base;
212 /* Type-specific fields go here. */
213} MemAllocObject;
214
215
216static int
217get_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;
2
Assuming 'buflen' is non-null
3
Taking false branch
227
228 bufptr = PyObject_GetAttrString(self, "_bufptr_");
229 if (!bufptr) goto cleanup;
4
Assuming 'bufptr' is non-null
5
Taking false branch
230
231 size = PyNumber_AsSsize_t(buflen, PyExc_OverflowError);
232 if (size == -1 && PyErr_Occurred()) goto cleanup;
6
Assuming the condition is false
233 else if (size < 0) {
7
Assuming 'size' is >= 0
8
Taking false branch
234 PyErr_SetString(PyExc_ValueError, "negative buffer size");
235 goto cleanup;
236 }
237
238 ptr = PyLong_AsVoidPtr(PyNumber_Long(bufptr));
9
Calling 'PyNumber_Long'
11
Returning from 'PyNumber_Long'
12
PyObject ownership leak with reference count of 1
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;
249cleanup:
250 Py_XDECREF(buflen)_Py_XDECREF(((PyObject*)(buflen)));
251 Py_XDECREF(bufptr)_Py_XDECREF(((PyObject*)(bufptr)));
252 return ret;
253}
254
255
256static int
257MemAllocObject_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))
1
Calling 'get_bufinfo'
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
275static void
276MemAllocObject_releasebuffer(PyObject *self, Py_buffer *view)
277{
278 /* Do nothing */
279}
280
281static PyBufferProcs MemAlloc_as_buffer = {
282 MemAllocObject_getbuffer,
283 MemAllocObject_releasebuffer,
284};
285
286
287static 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
344static 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
354MOD_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

/opt/pyrefcon/lib/pyrefcon/models/models/PyNumber_Long.model

1#ifndef PyNumber_Long
2PyObject* clang_analyzer_PyObject_New_Reference();
3PyObject* PyNumber_Long(PyObject *o) {
4 return clang_analyzer_PyObject_New_Reference();
10
Setting reference count to 1
5}
6#else
7#warning "API PyNumber_Long is defined as a macro."
8#endif