bpo-22273: Update ctypes to correctly handle arrays in small structur… · python/cpython@ce62dcc (original) (raw)

`@@ -350,6 +350,9 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct

`

350

350

`int pack;

`

351

351

`Py_ssize_t ffi_ofs;

`

352

352

`int big_endian;

`

``

353

`+

#if defined(X86_64)

`

``

354

`+

int arrays_seen = 0;

`

``

355

`+

#endif

`

353

356

``

354

357

`/* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to

`

355

358

` be a way to use the old, broken semantics: fields are not extended

`

`@@ -501,6 +504,10 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct

`

501

504

`Py_XDECREF(pair);

`

502

505

`return -1;

`

503

506

` }

`

``

507

`+

#if defined(X86_64)

`

``

508

`+

if (PyCArrayTypeObject_Check(desc))

`

``

509

`+

arrays_seen = 1;

`

``

510

`+

#endif

`

504

511

`dict = PyType_stgdict(desc);

`

505

512

`if (dict == NULL) {

`

506

513

`Py_DECREF(pair);

`

`@@ -641,6 +648,106 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct

`

641

648

`stgdict->align = total_align;

`

642

649

`stgdict->length = len; /* ADD ffi_ofs? */

`

643

650

``

``

651

`+

#if defined(X86_64)

`

``

652

+

``

653

`+

#define MAX_ELEMENTS 16

`

``

654

+

``

655

`+

if (arrays_seen && (size <= 16)) {

`

``

656

`+

/*

`

``

657

`+

`

``

658

`+

`

``

659

`+

`

``

660

`+

`

``

661

`+

`

``

662

`+

`

``

663

`+

`

``

664

`+

`

``

665

`+

`

``

666

`+

`

``

667

`+

`

``

668

`+

`

``

669

`+

`

``

670

`+

`

``

671

`+

`

``

672

`+

*/

`

``

673

`+

ffi_type *actual_types[MAX_ELEMENTS + 1];

`

``

674

`+

int actual_type_index = 0;

`

``

675

+

``

676

`+

memset(actual_types, 0, sizeof(actual_types));

`

``

677

`+

for (i = 0; i < len; ++i) {

`

``

678

`+

PyObject *name, *desc;

`

``

679

`+

PyObject *pair = PySequence_GetItem(fields, i);

`

``

680

`+

StgDictObject *dict;

`

``

681

`+

int bitsize = 0;

`

``

682

+

``

683

`+

if (pair == NULL) {

`

``

684

`+

return -1;

`

``

685

`+

}

`

``

686

`+

if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {

`

``

687

`+

PyErr_SetString(PyExc_TypeError,

`

``

688

`+

"'fields' must be a sequence of (name, C type) pairs");

`

``

689

`+

Py_XDECREF(pair);

`

``

690

`+

return -1;

`

``

691

`+

}

`

``

692

`+

dict = PyType_stgdict(desc);

`

``

693

`+

if (dict == NULL) {

`

``

694

`+

Py_DECREF(pair);

`

``

695

`+

PyErr_Format(PyExc_TypeError,

`

``

696

`+

"second item in fields tuple (index %zd) must be a C type",

`

``

697

`+

i);

`

``

698

`+

return -1;

`

``

699

`+

}

`

``

700

`+

if (!PyCArrayTypeObject_Check(desc)) {

`

``

701

`+

/* Not an array. Just copy over the element ffi_type. */

`

``

702

`+

actual_types[actual_type_index++] = &dict->ffi_type_pointer;

`

``

703

`+

assert(actual_type_index <= MAX_ELEMENTS);

`

``

704

`+

}

`

``

705

`+

else {

`

``

706

`+

int length = dict->length;

`

``

707

`+

StgDictObject *edict;

`

``

708

+

``

709

`+

edict = PyType_stgdict(dict->proto);

`

``

710

`+

if (edict == NULL) {

`

``

711

`+

Py_DECREF(pair);

`

``

712

`+

PyErr_Format(PyExc_TypeError,

`

``

713

`+

"second item in fields tuple (index %zd) must be a C type",

`

``

714

`+

i);

`

``

715

`+

return -1;

`

``

716

`+

}

`

``

717

`+

/* Copy over the element's type, length times. */

`

``

718

`+

while (length > 0) {

`

``

719

`+

actual_types[actual_type_index++] = &edict->ffi_type_pointer;

`

``

720

`+

assert(actual_type_index <= MAX_ELEMENTS);

`

``

721

`+

length--;

`

``

722

`+

}

`

``

723

`+

}

`

``

724

`+

Py_DECREF(pair);

`

``

725

`+

}

`

``

726

+

``

727

`+

actual_types[actual_type_index++] = NULL;

`

``

728

`+

/*

`

``

729

`+

`

``

730

`+

`

``

731

`+

*/

`

``

732

`+

assert(stgdict->ffi_type_pointer.elements);

`

``

733

`+

PyMem_Free(stgdict->ffi_type_pointer.elements);

`

``

734

`+

stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *,

`

``

735

`+

ffi_ofs + actual_type_index);

`

``

736

`+

if (stgdict->ffi_type_pointer.elements == NULL) {

`

``

737

`+

PyErr_NoMemory();

`

``

738

`+

return -1;

`

``

739

`+

}

`

``

740

`+

if (ffi_ofs) {

`

``

741

`+

memcpy(stgdict->ffi_type_pointer.elements,

`

``

742

`+

basedict->ffi_type_pointer.elements,

`

``

743

`+

ffi_ofs * sizeof(ffi_type *));

`

``

744

+

``

745

`+

}

`

``

746

`+

memcpy(&stgdict->ffi_type_pointer.elements[ffi_ofs], actual_types,

`

``

747

`+

actual_type_index * sizeof(ffi_type *));

`

``

748

`+

}

`

``

749

`+

#endif

`

``

750

+

644

751

`/* We did check that this flag was NOT set above, it must not

`

645

752

` have been set until now. */

`

646

753

`if (stgdict->flags & DICTFLAG_FINAL) {

`