Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(8)

Side by Side Diff: Modules/_ctypes/_ctypes.c

Issue 10744: ctypes arrays have incorrect buffer information (PEP-3118)
Patch Set: Created 5 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/ctypes/test/test_pep3118.py ('k') | Modules/_ctypes/ctypes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ToDo: 2 ToDo:
3 3
4 Get rid of the checker (and also the converters) field in PyCFuncPtrObject and 4 Get rid of the checker (and also the converters) field in PyCFuncPtrObject and
5 StgDictObject, and replace them by slot functions in StgDictObject. 5 StgDictObject, and replace them by slot functions in StgDictObject.
6 6
7 think about a buffer-like object (memory? bytes?) 7 think about a buffer-like object (memory? bytes?)
8 8
9 Should POINTER(c_char) and POINTER(c_wchar) have a .value property? 9 Should POINTER(c_char) and POINTER(c_wchar) have a .value property?
10 What about c_char and c_wchar arrays then? 10 What about c_char and c_wchar arrays then?
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 if (result == NULL) { 279 if (result == NULL) {
280 PyErr_NoMemory(); 280 PyErr_NoMemory();
281 return NULL; 281 return NULL;
282 } 282 }
283 if (prefix) 283 if (prefix)
284 strcpy(result, prefix); 284 strcpy(result, prefix);
285 else 285 else
286 result[0] = '\0'; 286 result[0] = '\0';
287 strcat(result, suffix); 287 strcat(result, suffix);
288 return result; 288 return result;
289 }
290
291 /*
292 Allocate a memory block for a pep3118 format string, adding
293 the given prefix (if non-null), an additional shape prefix, and a suffix.
294 Returns NULL on failure, with the error indicator set. If called with
295 a suffix of NULL the error indicator must already be set.
296 */
297 char *
298 _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
299 const char *prefix, const char *suffix)
300 {
301 char *new_prefix;
302 char *result;
303 char buf[32];
304 int prefix_len;
305 int k;
306
307 prefix_len = 32 * ndim + 3;
308 if (prefix)
309 prefix_len += strlen(prefix);
310 new_prefix = PyMem_Malloc(prefix_len);
311 if (new_prefix == NULL)
312 return NULL;
313 new_prefix[0] = '\0';
314 if (prefix)
315 strcpy(new_prefix, prefix);
316 if (ndim > 0) {
317 /* Add the prefix "(shape[0],shape[1],...,shape[ndim-1])" */
318 strcat(new_prefix, "(");
319 for (k = 0; k < ndim; ++k) {
320 if (k < ndim-1) {
321 sprintf(buf, "%"PY_FORMAT_SIZE_T"d,", shape[k]);
322 } else {
323 sprintf(buf, "%"PY_FORMAT_SIZE_T"d)", shape[k]);
324 }
325 strcat(new_prefix, buf);
326 }
327 }
328 result = _ctypes_alloc_format_string(new_prefix, suffix);
329 PyMem_Free(new_prefix);
330 return result;
289 } 331 }
290 332
291 /* 333 /*
292 PyCStructType_Type - a meta type/class. Creating a new class using this one a s 334 PyCStructType_Type - a meta type/class. Creating a new class using this one a s
293 __metaclass__ will call the contructor StructUnionType_new. It replaces the 335 __metaclass__ will call the contructor StructUnionType_new. It replaces the
294 tp_dict member with a new instance of StgDict, and initializes the C 336 tp_dict member with a new instance of StgDict, and initializes the C
295 accessible fields somehow. 337 accessible fields somehow.
296 */ 338 */
297 339
298 static PyCArgObject * 340 static PyCArgObject *
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 stgdict->flags |= TYPEFLAG_ISPOINTER; 895 stgdict->flags |= TYPEFLAG_ISPOINTER;
854 896
855 proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */ 897 proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
856 if (proto && -1 == PyCPointerType_SetProto(stgdict, proto)) { 898 if (proto && -1 == PyCPointerType_SetProto(stgdict, proto)) {
857 Py_DECREF((PyObject *)stgdict); 899 Py_DECREF((PyObject *)stgdict);
858 return NULL; 900 return NULL;
859 } 901 }
860 902
861 if (proto) { 903 if (proto) {
862 StgDictObject *itemdict = PyType_stgdict(proto); 904 StgDictObject *itemdict = PyType_stgdict(proto);
905 const char *current_format;
863 assert(itemdict); 906 assert(itemdict);
864 /* If itemdict->format is NULL, then this is a pointer to an 907 /* If itemdict->format is NULL, then this is a pointer to an
865 incomplete type. We create a generic format string 908 incomplete type. We create a generic format string
866 'pointer to bytes' in this case. XXX Better would be to 909 'pointer to bytes' in this case. XXX Better would be to
867 fix the format string later... 910 fix the format string later...
868 */ 911 */
869 stgdict->format = _ctypes_alloc_format_string("&", 912 current_format = itemdict->format ? itemdict->format : "B";
870 itemdict->format ? itemdict->format : "B"); 913 if (itemdict->shape != NULL) {
914 /* pointer to an array: the shape needs to be prefixed */
915 stgdict->format = _ctypes_alloc_format_string_with_shape(
916 itemdict->ndim, itemdict->shape, "&", current_format);
917 } else {
918 stgdict->format = _ctypes_alloc_format_string("&", current_format);
919 }
871 if (stgdict->format == NULL) { 920 if (stgdict->format == NULL) {
872 Py_DECREF((PyObject *)stgdict); 921 Py_DECREF((PyObject *)stgdict);
873 return NULL; 922 return NULL;
874 } 923 }
875 } 924 }
876 925
877 /* create the new instance (which is a class, 926 /* create the new instance (which is a class,
878 since we are a metatype!) */ 927 since we are a metatype!) */
879 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); 928 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
880 if (result == NULL) { 929 if (result == NULL) {
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 static PyObject * 1287 static PyObject *
1239 PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 1288 PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1240 { 1289 {
1241 PyTypeObject *result; 1290 PyTypeObject *result;
1242 StgDictObject *stgdict; 1291 StgDictObject *stgdict;
1243 StgDictObject *itemdict; 1292 StgDictObject *itemdict;
1244 PyObject *length_attr, *type_attr; 1293 PyObject *length_attr, *type_attr;
1245 long length; 1294 long length;
1246 int overflow; 1295 int overflow;
1247 Py_ssize_t itemsize, itemalign; 1296 Py_ssize_t itemsize, itemalign;
1248 char buf[32];
1249 1297
1250 /* create the new instance (which is a class, 1298 /* create the new instance (which is a class,
1251 since we are a metatype!) */ 1299 since we are a metatype!) */
1252 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds); 1300 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
1253 if (result == NULL) 1301 if (result == NULL)
1254 return NULL; 1302 return NULL;
1255 1303
1256 /* Initialize these variables to NULL so that we can simplify error 1304 /* Initialize these variables to NULL so that we can simplify error
1257 handling by using Py_XDECREF. */ 1305 handling by using Py_XDECREF. */
1258 stgdict = NULL; 1306 stgdict = NULL;
(...skipping 29 matching lines...) Expand all
1288 goto error; 1336 goto error;
1289 1337
1290 itemdict = PyType_stgdict(type_attr); 1338 itemdict = PyType_stgdict(type_attr);
1291 if (!itemdict) { 1339 if (!itemdict) {
1292 PyErr_SetString(PyExc_TypeError, 1340 PyErr_SetString(PyExc_TypeError,
1293 "_type_ must have storage info"); 1341 "_type_ must have storage info");
1294 goto error; 1342 goto error;
1295 } 1343 }
1296 1344
1297 assert(itemdict->format); 1345 assert(itemdict->format);
1298 if (itemdict->format[0] == '(') { 1346 stgdict->format = _ctypes_alloc_format_string(NULL, itemdict->format);
1299 sprintf(buf, "(%ld,", length);
1300 stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format+1);
1301 } else {
1302 sprintf(buf, "(%ld)", length);
1303 stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format);
1304 }
1305 if (stgdict->format == NULL) 1347 if (stgdict->format == NULL)
1306 goto error; 1348 goto error;
1307 stgdict->ndim = itemdict->ndim + 1; 1349 stgdict->ndim = itemdict->ndim + 1;
1308 stgdict->shape = PyMem_Malloc(sizeof(Py_ssize_t) * stgdict->ndim); 1350 stgdict->shape = PyMem_Malloc(sizeof(Py_ssize_t) * stgdict->ndim);
1309 if (stgdict->shape == NULL) { 1351 if (stgdict->shape == NULL) {
1310 PyErr_NoMemory(); 1352 PyErr_NoMemory();
1311 goto error; 1353 goto error;
1312 } 1354 }
1313 stgdict->shape[0] = length; 1355 stgdict->shape[0] = length;
1314 memmove(&stgdict->shape[1], itemdict->shape, 1356 memmove(&stgdict->shape[1], itemdict->shape,
(...skipping 4147 matching lines...) Expand 10 before | Expand all | Expand 10 after
5462 PyModule_AddObject(m, "ArgumentError", PyExc_ArgError); 5504 PyModule_AddObject(m, "ArgumentError", PyExc_ArgError);
5463 } 5505 }
5464 return m; 5506 return m;
5465 } 5507 }
5466 5508
5467 /* 5509 /*
5468 Local Variables: 5510 Local Variables:
5469 compile-command: "cd .. && python setup.py -q build -g && python setup.py -q bu ild install --home ~" 5511 compile-command: "cd .. && python setup.py -q build -g && python setup.py -q bu ild install --home ~"
5470 End: 5512 End:
5471 */ 5513 */
OLDNEW
« no previous file with comments | « Lib/ctypes/test/test_pep3118.py ('k') | Modules/_ctypes/ctypes.h » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+