### Bug Summary

File: | Modules/_ctypes/callbacks.c
Location: | line 270, column 20
Description: | Dereference of undefined pointer value

### Annotated Source Code

1 | #include "Python.h"
2 | #include "frameobject.h"
3 |
4 | #include <ffi.h>
5 | #ifdef MS_WIN32
6 | #include <windows.h>
7 | #endif
8 | #include "ctypes.h"
9 |
10 | /**************************************************************/
11 |
12 | static void
13 | CThunkObject_dealloc(PyObject *_self)
14 | {
15 | CThunkObject *self = (CThunkObject *)_self;
16 | Py_XDECREF(self->converters)do { if ((self->converters) == ((void*)0)) ; else do { if ( _Py_RefTotal-- , --((PyObject*)(self->converters))->ob_refcnt != 0) { if (((PyObject*)self->converters)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 16, (PyObject *)(self->converters)); } else _Py_Dealloc( (PyObject *)(self->converters)); } while (0); } while (0);
17 | Py_XDECREF(self->callable)do { if ((self->callable) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(self->callable))->ob_refcnt != 0) { if (((PyObject*)self->callable)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 17, (PyObject *)(self->callable)); } else _Py_Dealloc((PyObject *)(self->callable)); } while (0); } while (0);
18 | Py_XDECREF(self->restype)do { if ((self->restype) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(self->restype))->ob_refcnt != 0) { if (((PyObject*)self->restype)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 18, (PyObject *)(self->restype)); } else _Py_Dealloc((PyObject *)(self->restype)); } while (0); } while (0);
19 | if (self->pcl_write)
20 | ffi_closure_free(self->pcl_write);
21 | PyObject_GC_Del(self);
22 | }
23 |
24 | static int
25 | CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg)
26 | {
27 | CThunkObject *self = (CThunkObject *)_self;
28 | Py_VISIT(self->converters)do { if (self->converters) { int vret = visit((PyObject *) (self->converters), arg); if (vret) return vret; } } while (0);
29 | Py_VISIT(self->callable)do { if (self->callable) { int vret = visit((PyObject *)(self ->callable), arg); if (vret) return vret; } } while (0);
30 | Py_VISIT(self->restype)do { if (self->restype) { int vret = visit((PyObject *)(self ->restype), arg); if (vret) return vret; } } while (0);
31 | return 0;
32 | }
33 |
34 | static int
35 | CThunkObject_clear(PyObject *_self)
36 | {
37 | CThunkObject *self = (CThunkObject *)_self;
38 | Py_CLEAR(self->converters)do { if (self->converters) { PyObject *_py_tmp = (PyObject *)(self->converters); (self->converters) = ((void*)0); do { if (_Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 38, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0);
39 | Py_CLEAR(self->callable)do { if (self->callable) { PyObject *_py_tmp = (PyObject * )(self->callable); (self->callable) = ((void*)0); do { if (_Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0 ) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 39, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0);
40 | Py_CLEAR(self->restype)do { if (self->restype) { PyObject *_py_tmp = (PyObject *) (self->restype); (self->restype) = ((void*)0); do { if ( _Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 40, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0);
41 | return 0;
42 | }
43 |
44 | PyTypeObject PyCThunk_Type = {
45 | PyVarObject_HEAD_INIT(NULL, 0){ { 0, 0, 1, ((void*)0) }, 0 },
46 | "_ctypes.CThunkObject",
47 | sizeof(CThunkObject), /* tp_basicsize */
48 | sizeof(ffi_type), /* tp_itemsize */
49 | CThunkObject_dealloc, /* tp_dealloc */
50 | 0, /* tp_print */
51 | 0, /* tp_getattr */
52 | 0, /* tp_setattr */
53 | 0, /* tp_reserved */
54 | 0, /* tp_repr */
55 | 0, /* tp_as_number */
56 | 0, /* tp_as_sequence */
57 | 0, /* tp_as_mapping */
58 | 0, /* tp_hash */
59 | 0, /* tp_call */
60 | 0, /* tp_str */
61 | 0, /* tp_getattro */
62 | 0, /* tp_setattro */
63 | 0, /* tp_as_buffer */
64 | Py_TPFLAGS_DEFAULT( 0 | (1L<<18) | 0) | Py_TPFLAGS_HAVE_GC(1L<<14), /* tp_flags */
65 | "CThunkObject", /* tp_doc */
66 | CThunkObject_traverse, /* tp_traverse */
67 | CThunkObject_clear, /* tp_clear */
68 | 0, /* tp_richcompare */
69 | 0, /* tp_weaklistoffset */
70 | 0, /* tp_iter */
71 | 0, /* tp_iternext */
72 | 0, /* tp_methods */
73 | 0, /* tp_members */
74 | };
75 |
76 | /**************************************************************/
77 |
78 | static void
79 | PrintError(char *msg, ...)
80 | {
81 | char buf[512];
82 | PyObject *f = PySys_GetObject("stderr");
83 | va_list marker;
84 |
85 | va_start(marker, msg)__builtin_va_start(marker, msg);
86 | vsnprintf(buf, sizeof(buf), msg, marker)__builtin___vsnprintf_chk (buf, sizeof(buf), 0, __builtin_object_size (buf, 2 > 1), msg, marker);
87 | va_end(marker)__builtin_va_end(marker);
88 | if (f != NULL((void*)0) && f != Py_None(&_Py_NoneStruct))
89 | PyFile_WriteString(buf, f);
90 | PyErr_Print();
91 | }
92 |
93 |
94 | /* after code that pyrex generates */
95 | void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
96 | {
97 | PyObject *py_globals = 0;
98 | PyCodeObject *py_code = 0;
99 | PyFrameObject *py_frame = 0;
100 |
101 | py_globals = PyDict_New();
102 | if (!py_globals) goto bad;
103 | py_code = PyCode_NewEmpty(filename, funcname, lineno);
104 | if (!py_code) goto bad;
105 | py_frame = PyFrame_New(
106 | PyThreadState_Get(), /*PyThreadState *tstate,*/
107 | py_code, /*PyCodeObject *code,*/
108 | py_globals, /*PyObject *globals,*/
109 | 0 /*PyObject *locals*/
110 | );
111 | if (!py_frame) goto bad;
112 | py_frame->f_lineno = lineno;
113 | PyTraceBack_Here(py_frame);
114 | bad:
115 | Py_XDECREF(py_globals)do { if ((py_globals) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_globals))->ob_refcnt != 0) { if ((( PyObject*)py_globals)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 115, (PyObject *)(py_globals)); } else _Py_Dealloc((PyObject *)(py_globals)); } while (0); } while (0);
116 | Py_XDECREF(py_code)do { if ((py_code) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_code))->ob_refcnt != 0) { if (((PyObject *)py_code)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 116, (PyObject *)(py_code)); } else _Py_Dealloc((PyObject * )(py_code)); } while (0); } while (0);
117 | Py_XDECREF(py_frame)do { if ((py_frame) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_frame))->ob_refcnt != 0) { if (((PyObject *)py_frame)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 117, (PyObject *)(py_frame)); } else _Py_Dealloc((PyObject * )(py_frame)); } while (0); } while (0);
118 | }
119 |
120 | #ifdef MS_WIN32
121 | /*
122 | * We must call AddRef() on non-NULL COM pointers we receive as arguments
123 | * to callback functions - these functions are COM method implementations.
124 | * The Python instances we create have a __del__ method which calls Release().
125 | *
126 | * The presence of a class attribute named '_needs_com_addref_' triggers this
127 | * behaviour. It would also be possible to call the AddRef() Python method,
128 | * after checking for PyObject_IsTrue(), but this would probably be somewhat
129 | * slower.
130 | */
131 | static void
132 | TryAddRef(StgDictObject *dict, CDataObject *obj)
133 | {
134 | IUnknown *punk;
135 |
136 | if (NULL((void*)0) == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_"))
137 | return;
138 |
139 | punk = *(IUnknown **)obj->b_ptr;
140 | if (punk)
141 | punk->lpVtbl->AddRef(punk);
142 | return;
143 | }
144 | #endif
145 |
146 | /******************************************************************************
147 | *
148 | * Call the python object with all arguments
149 | *
150 | */
151 | static void _CallPythonObject(void *mem,
152 | ffi_type *restype,
153 | SETFUNC setfunc,
154 | PyObject *callable,
155 | PyObject *converters,
156 | int flags,
157 | void **pArgs)
158 | {
159 | Py_ssize_t i;
160 | PyObject *result;
161 | PyObject *arglist = NULL((void*)0);
162 | Py_ssize_t nArgs;
163 | PyObject *error_object = NULL((void*)0);
164 | int *space;
165 | #ifdef WITH_THREAD1
166 | PyGILState_STATE state = PyGILState_Ensure();
167 | #endif
168 |
169 | nArgs = PySequence_LengthPySequence_Size(converters);
170 | /* Hm. What to return in case of error?
171 | For COM, 0xFFFFFFFF seems better than 0.
172 | */
173 | if (nArgs < 0) {
1 | Taking false branch
174 | PrintError("BUG: PySequence_Length");
175 | goto Done;
176 | }
177 |
178 | arglist = PyTuple_New(nArgs);
179 | if (!arglist) {
2 | Taking false branch
180 | PrintError("PyTuple_New()");
181 | goto Done;
182 | }
183 | for (i = 0; i < nArgs; ++i) {
3 | Loop condition is false. Execution continues on line 241
184 | /* Note: new reference! */
185 | PyObject *cnv = PySequence_GetItem(converters, i);
186 | StgDictObject *dict;
187 | if (cnv)
188 | dict = PyType_stgdict(cnv);
189 | else {
190 | PrintError("Getting argument converter %d\n", i);
191 | goto Done;
192 | }
193 |
194 | if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) {
195 | PyObject *v = dict->getfunc(*pArgs, dict->size);
196 | if (!v) {
197 | PrintError("create argument %d:\n", i);
198 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 198, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
199 | goto Done;
200 | }
201 | PyTuple_SET_ITEM(arglist, i, v)(((PyTupleObject *)(arglist))->ob_item[i] = v);
202 | /* XXX XXX XX
203 | We have the problem that c_byte or c_short have dict->size of
204 | 1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
205 | BTW, the same problem occurrs when they are pushed as parameters
206 | */
207 | } else if (dict) {
208 | /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
209 | CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL((void*)0));
210 | if (!obj) {
211 | PrintError("create argument %d:\n", i);
212 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 212, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
213 | goto Done;
214 | }
215 | if (!CDataObject_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyCData_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyCData_Type)))) {
216 | Py_DECREF(obj)do { if (_Py_RefTotal-- , --((PyObject*)(obj))->ob_refcnt != 0) { if (((PyObject*)obj)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 216, (PyObject *)(obj)); } else _Py_Dealloc((PyObject *)(obj )); } while (0);
217 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 217, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
218 | PrintError("unexpected result of create argument %d:\n", i);
219 | goto Done;
220 | }
221 | memcpy(obj->b_ptr, *pArgs, dict->size)((__builtin_object_size (obj->b_ptr, 0) != (size_t) -1) ? __builtin___memcpy_chk (obj->b_ptr, *pArgs, dict->size, __builtin_object_size (obj->b_ptr, 0)) : __inline_memcpy_chk (obj->b_ptr, *pArgs , dict->size));
222 | PyTuple_SET_ITEM(arglist, i, (PyObject *)obj)(((PyTupleObject *)(arglist))->ob_item[i] = (PyObject *)obj );
223 | #ifdef MS_WIN32
224 | TryAddRef(dict, obj);
225 | #endif
226 | } else {
227 | PyErr_SetString(PyExc_TypeError,
228 | "cannot build parameter");
229 | PrintError("Parsing argument %d\n", i);
230 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 230, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
231 | goto Done;
232 | }
233 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 233, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
234 | /* XXX error handling! */
235 | pArgs++;
236 | }
237 |
238 | #define CHECK(what, x)if (x == ((void*)0)) _ctypes_add_traceback(what, "_ctypes/callbacks.c" , 238 - 1), PyErr_Print() \
239 | if (x == NULL((void*)0)) _ctypes_add_traceback(what, "_ctypes/callbacks.c", __LINE__239 - 1), PyErr_Print()
240 |
241 | if (flags & (FUNCFLAG_USE_ERRNO0x8 | FUNCFLAG_USE_LASTERROR0x10)) {
4 | Taking false branch
242 | error_object = _ctypes_get_errobj(&space);
243 | if (error_object == NULL((void*)0))
244 | goto Done;
245 | if (flags & FUNCFLAG_USE_ERRNO0x8) {
246 | int temp = space[0];
247 | space[0] = errno(*__error());
248 | errno(*__error()) = temp;
249 | }
250 | #ifdef MS_WIN32
251 | if (flags & FUNCFLAG_USE_LASTERROR0x10) {
252 | int temp = space[1];
253 | space[1] = GetLastError();
254 | SetLastError(temp);
255 | }
256 | #endif
257 | }
258 |
259 | result = PyObject_CallObject(callable, arglist);
260 | CHECK("'calling callback function'", result)if (result == ((void*)0)) _ctypes_add_traceback("'calling callback function'" , "_ctypes/callbacks.c", 260 - 1), PyErr_Print();
261 |
262 | #ifdef MS_WIN32
263 | if (flags & FUNCFLAG_USE_LASTERROR0x10) {
264 | int temp = space[1];
265 | space[1] = GetLastError();
266 | SetLastError(temp);
267 | }
268 | #endif
269 | if (flags & FUNCFLAG_USE_ERRNO0x8) {
5 | Taking true branch
270 | int temp = space[0];
6 | Dereference of undefined pointer value
271 | space[0] = errno(*__error());
272 | errno(*__error()) = temp;
273 | }
274 | Py_XDECREF(error_object)do { if ((error_object) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(error_object))->ob_refcnt != 0) { if ( ((PyObject*)error_object)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 274, (PyObject *)(error_object)); } else _Py_Dealloc((PyObject *)(error_object)); } while (0); } while (0);
275 |
276 | if ((restype != &ffi_type_void) && result) {
277 | PyObject *keep;
278 | assert(setfunc)(__builtin_expect(!(setfunc), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 278, "setfunc") : (void)0);
279 | #ifdef WORDS_BIGENDIAN
280 | /* See the corresponding code in callproc.c, around line 961 */
281 | if (restype->type != FFI_TYPE_FLOAT2 && restype->size < sizeof(ffi_arg))
282 | mem = (char *)mem + sizeof(ffi_arg) - restype->size;
283 | #endif
284 | keep = setfunc(mem, result, 0);
285 | CHECK("'converting callback result'", keep)if (keep == ((void*)0)) _ctypes_add_traceback("'converting callback result'" , "_ctypes/callbacks.c", 285 - 1), PyErr_Print();
286 | /* keep is an object we have to keep alive so that the result
287 | stays valid. If there is no such object, the setfunc will
288 | have returned Py_None.
289 |
290 | If there is such an object, we have no choice than to keep
291 | it alive forever - but a refcount and/or memory leak will
292 | be the result. EXCEPT when restype is py_object - Python
293 | itself knows how to manage the refcount of these objects.
294 | */
295 | if (keep == NULL((void*)0)) /* Could not convert callback result. */
296 | PyErr_WriteUnraisable(callable);
297 | else if (keep == Py_None(&_Py_NoneStruct)) /* Nothing to keep */
298 | Py_DECREF(keep)do { if (_Py_RefTotal-- , --((PyObject*)(keep))->ob_refcnt != 0) { if (((PyObject*)keep)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 298, (PyObject *)(keep)); } else _Py_Dealloc((PyObject *)(keep )); } while (0);
299 | else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
300 | if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning,
301 | "memory leak in callback function.",
302 | 1))
303 | PyErr_WriteUnraisable(callable);
304 | }
305 | }
306 | Py_XDECREF(result)do { if ((result) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject *)result)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 306, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0); } while (0);
307 | Done:
308 | Py_XDECREF(arglist)do { if ((arglist) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(arglist))->ob_refcnt != 0) { if (((PyObject *)arglist)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 308, (PyObject *)(arglist)); } else _Py_Dealloc((PyObject * )(arglist)); } while (0); } while (0);
309 | #ifdef WITH_THREAD1
310 | PyGILState_Release(state);
311 | #endif
312 | }
313 |
314 | static void closure_fcn(ffi_cif *cif,
315 | void *resp,
316 | void **args,
317 | void *userdata)
318 | {
319 | CThunkObject *p = (CThunkObject *)userdata;
320 |
321 | _CallPythonObject(resp,
322 | p->ffi_restype,
323 | p->setfunc,
324 | p->callable,
325 | p->converters,
326 | p->flags,
327 | args);
328 | }
329 |
330 | static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
331 | {
332 | CThunkObject *p;
333 | int i;
334 |
335 | p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs)( (CThunkObject *) _PyObject_GC_NewVar((&PyCThunk_Type), ( nArgs)) );
336 | if (p == NULL((void*)0)) {
337 | PyErr_NoMemory();
338 | return NULL((void*)0);
339 | }
340 |
341 | p->pcl_exec = NULL((void*)0);
342 | p->pcl_write = NULL((void*)0);
343 | memset(&p->cif, 0, sizeof(p->cif))((__builtin_object_size (&p->cif, 0) != (size_t) -1) ? __builtin___memset_chk (&p->cif, 0, sizeof(p->cif) , __builtin_object_size (&p->cif, 0)) : __inline_memset_chk (&p->cif, 0, sizeof(p->cif)));
344 | p->converters = NULL((void*)0);
345 | p->callable = NULL((void*)0);
346 | p->setfunc = NULL((void*)0);
347 | p->ffi_restype = NULL((void*)0);
348 |
349 | for (i = 0; i < nArgs + 1; ++i)
350 | p->atypes[i] = NULL((void*)0);
351 | PyObject_GC_Track((PyObject *)p);
352 | return p;
353 | }
354 |
355 | CThunkObject *_ctypes_alloc_callback(PyObject *callable,
356 | PyObject *converters,
357 | PyObject *restype,
358 | int flags)
359 | {
360 | int result;
361 | CThunkObject *p;
362 | Py_ssize_t nArgs, i;
363 | ffi_abi cc;
364 |
365 | nArgs = PySequence_Size(converters);
366 | p = CThunkObject_new(nArgs);
367 | if (p == NULL((void*)0))
368 | return NULL((void*)0);
369 |
370 | assert(CThunk_CheckExact((PyObject *)p))(__builtin_expect(!((((PyObject *)p)->ob_type == &PyCThunk_Type )), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 370, "CThunk_CheckExact((PyObject *)p)") : (void)0);
371 |
372 | p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
373 | &p->pcl_exec);
374 | if (p->pcl_write == NULL((void*)0)) {
375 | PyErr_NoMemory();
376 | goto error;
377 | }
378 |
379 | p->flags = flags;
380 | for (i = 0; i < nArgs; ++i) {
381 | PyObject *cnv = PySequence_GetItem(converters, i);
382 | if (cnv == NULL((void*)0))
383 | goto error;
384 | p->atypes[i] = _ctypes_get_ffi_type(cnv);
385 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 385, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0);
386 | }
387 | p->atypes[i] = NULL((void*)0);
388 |
389 | Py_INCREF(restype)( _Py_RefTotal++ , ((PyObject*)(restype))->ob_refcnt++);
390 | p->restype = restype;
391 | if (restype == Py_None(&_Py_NoneStruct)) {
392 | p->setfunc = NULL((void*)0);
393 | p->ffi_restype = &ffi_type_void;
394 | } else {
395 | StgDictObject *dict = PyType_stgdict(restype);
396 | if (dict == NULL((void*)0) || dict->setfunc == NULL((void*)0)) {
397 | PyErr_SetString(PyExc_TypeError,
398 | "invalid result type for callback function");
399 | goto error;
400 | }
401 | p->setfunc = dict->setfunc;
402 | p->ffi_restype = &dict->ffi_type_pointer;
403 | }
404 |
405 | cc = FFI_DEFAULT_ABI;
406 | #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64)
407 | if ((flags & FUNCFLAG_CDECL0x1) == 0)
408 | cc = FFI_STDCALL;
409 | #endif
410 | result = ffi_prep_cif(&p->cif, cc,
411 | Py_SAFE_DOWNCAST(nArgs, Py_ssize_t, int)((__builtin_expect(!((Py_ssize_t)(int)(nArgs) == (nArgs)), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 411, "(Py_ssize_t)(int)(nArgs) == (nArgs)") : (void)0), (int )(nArgs)),
412 | _ctypes_get_ffi_type(restype),
413 | &p->atypes[0]);
414 | if (result != FFI_OK) {
415 | PyErr_Format(PyExc_RuntimeError,
416 | "ffi_prep_cif failed with %d", result);
417 | goto error;
418 | }
419 | #if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
420 | result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
421 | #else
422 | result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
423 | p,
424 | p->pcl_exec);
425 | #endif
426 | if (result != FFI_OK) {
427 | PyErr_Format(PyExc_RuntimeError,
428 | "ffi_prep_closure failed with %d", result);
429 | goto error;
430 | }
431 |
432 | Py_INCREF(converters)( _Py_RefTotal++ , ((PyObject*)(converters))->ob_refcnt++);
433 | p->converters = converters;
434 | Py_INCREF(callable)( _Py_RefTotal++ , ((PyObject*)(callable))->ob_refcnt++);
435 | p->callable = callable;
436 | return p;
437 |
438 | error:
439 | Py_XDECREF(p)do { if ((p) == ((void*)0)) ; else do { if (_Py_RefTotal-- , -- ((PyObject*)(p))->ob_refcnt != 0) { if (((PyObject*)p)-> ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 439, (PyObject *)(p)); } else _Py_Dealloc((PyObject *)(p)); } while (0); } while (0);
440 | return NULL((void*)0);
441 | }
442 |
443 | #ifdef MS_WIN32
444 |
445 | static void LoadPython(void)
446 | {
447 | if (!Py_IsInitialized()) {
448 | #ifdef WITH_THREAD1
449 | PyEval_InitThreads();
450 | #endif
451 | Py_Initialize();
452 | }
453 | }
454 |
455 | /******************************************************************/
456 |
457 | long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
458 | {
459 | PyObject *mod, *func, *result;
460 | long retval;
461 | static PyObject *context;
462 |
463 | if (context == NULL((void*)0))
464 | context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
465 |
466 | mod = PyImport_ImportModuleNoBlock("ctypes");
467 | if (!mod) {
468 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
469 | /* There has been a warning before about this already */
470 | return E_FAIL;
471 | }
472 |
473 | func = PyObject_GetAttrString(mod, "DllGetClassObject");
474 | Py_DECREF(mod)do { if (_Py_RefTotal-- , --((PyObject*)(mod))->ob_refcnt != 0) { if (((PyObject*)mod)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 474, (PyObject *)(mod)); } else _Py_Dealloc((PyObject *)(mod )); } while (0);
475 | if (!func) {
476 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
477 | return E_FAIL;
478 | }
479 |
480 | {
481 | PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
482 | PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
483 | PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
484 | if (!py_rclsid || !py_riid || !py_ppv) {
485 | Py_XDECREF(py_rclsid)do { if ((py_rclsid) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_rclsid))->ob_refcnt != 0) { if (((PyObject *)py_rclsid)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 485, (PyObject *)(py_rclsid)); } else _Py_Dealloc((PyObject *)(py_rclsid)); } while (0); } while (0);
486 | Py_XDECREF(py_riid)do { if ((py_riid) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_riid))->ob_refcnt != 0) { if (((PyObject *)py_riid)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 486, (PyObject *)(py_riid)); } else _Py_Dealloc((PyObject * )(py_riid)); } while (0); } while (0);
487 | Py_XDECREF(py_ppv)do { if ((py_ppv) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_ppv))->ob_refcnt != 0) { if (((PyObject *)py_ppv)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 487, (PyObject *)(py_ppv)); } else _Py_Dealloc((PyObject *) (py_ppv)); } while (0); } while (0);
488 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 488, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0);
489 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
490 | return E_FAIL;
491 | }
492 | result = PyObject_CallFunctionObjArgs(func,
493 | py_rclsid,
494 | py_riid,
495 | py_ppv,
496 | NULL((void*)0));
497 | Py_DECREF(py_rclsid)do { if (_Py_RefTotal-- , --((PyObject*)(py_rclsid))->ob_refcnt != 0) { if (((PyObject*)py_rclsid)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 497, (PyObject *)(py_rclsid)); } else _Py_Dealloc((PyObject *)(py_rclsid)); } while (0);
498 | Py_DECREF(py_riid)do { if (_Py_RefTotal-- , --((PyObject*)(py_riid))->ob_refcnt != 0) { if (((PyObject*)py_riid)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 498, (PyObject *)(py_riid)); } else _Py_Dealloc((PyObject * )(py_riid)); } while (0);
499 | Py_DECREF(py_ppv)do { if (_Py_RefTotal-- , --((PyObject*)(py_ppv))->ob_refcnt != 0) { if (((PyObject*)py_ppv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 499, (PyObject *)(py_ppv)); } else _Py_Dealloc((PyObject *) (py_ppv)); } while (0);
500 | }
501 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 501, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0);
502 | if (!result) {
503 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
504 | return E_FAIL;
505 | }
506 |
507 | retval = PyLong_AsLong(result);
508 | if (PyErr_Occurred()) {
509 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
510 | retval = E_FAIL;
511 | }
512 | Py_DECREF(result)do { if (_Py_RefTotal-- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject*)result)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 512, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0);
513 | return retval;
514 | }
515 |
516 | STDAPI DllGetClassObject(REFCLSID rclsid,
517 | REFIID riid,
518 | LPVOID *ppv)
519 | {
520 | long result;
521 | #ifdef WITH_THREAD1
522 | PyGILState_STATE state;
523 | #endif
524 |
525 | LoadPython();
526 | #ifdef WITH_THREAD1
527 | state = PyGILState_Ensure();
528 | #endif
529 | result = Call_GetClassObject(rclsid, riid, ppv);
530 | #ifdef WITH_THREAD1
531 | PyGILState_Release(state);
532 | #endif
533 | return result;
534 | }
535 |
536 | long Call_CanUnloadNow(void)
537 | {
538 | PyObject *mod, *func, *result;
539 | long retval;
540 | static PyObject *context;
541 |
542 | if (context == NULL((void*)0))
543 | context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow");
544 |
545 | mod = PyImport_ImportModuleNoBlock("ctypes");
546 | if (!mod) {
547 | /* OutputDebugString("Could not import ctypes"); */
548 | /* We assume that this error can only occur when shutting
549 | down, so we silently ignore it */
550 | PyErr_Clear();
551 | return E_FAIL;
552 | }
553 | /* Other errors cannot be raised, but are printed to stderr */
554 | func = PyObject_GetAttrString(mod, "DllCanUnloadNow");
555 | Py_DECREF(mod)do { if (_Py_RefTotal-- , --((PyObject*)(mod))->ob_refcnt != 0) { if (((PyObject*)mod)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 555, (PyObject *)(mod)); } else _Py_Dealloc((PyObject *)(mod )); } while (0);
556 | if (!func) {
557 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
558 | return E_FAIL;
559 | }
560 |
561 | result = PyObject_CallFunction(func, NULL((void*)0));
562 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 562, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0);
563 | if (!result) {
564 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
565 | return E_FAIL;
566 | }
567 |
568 | retval = PyLong_AsLong(result);
569 | if (PyErr_Occurred()) {
570 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct));
571 | retval = E_FAIL;
572 | }
573 | Py_DECREF(result)do { if (_Py_RefTotal-- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject*)result)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 573, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0);
574 | return retval;
575 | }
576 |
577 | /*
578 | DllRegisterServer and DllUnregisterServer still missing
579 | */
580 |
581 | STDAPI DllCanUnloadNow(void)
582 | {
583 | long result;
584 | #ifdef WITH_THREAD1
585 | PyGILState_STATE state = PyGILState_Ensure();
586 | #endif
587 | result = Call_CanUnloadNow();
588 | #ifdef WITH_THREAD1
589 | PyGILState_Release(state);
590 | #endif
591 | return result;
592 | }
593 |
594 | #ifndef Py_NO_ENABLE_SHARED
595 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes)
596 | {
597 | switch(fdwReason) {
598 | case DLL_PROCESS_ATTACH:
599 | DisableThreadLibraryCalls(hinstDLL);
600 | break;
601 | }
602 | return TRUE;
603 | }
604 | #endif
605 |
606 | #endif
607 |
608 | /*
609 | Local Variables:
610 | compile-command: "cd .. && python setup.py -q build_ext"
611 | End:
612 | */