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

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

`

344

344

`int pack = 0;

`

345

345

`Py_ssize_t ffi_ofs;

`

346

346

`int big_endian;

`

``

347

`+

#if defined(X86_64)

`

``

348

`+

int arrays_seen = 0;

`

``

349

`+

#endif

`

347

350

``

348

351

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

`

349

352

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

`

`@@ -468,6 +471,10 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct

`

468

471

`Py_XDECREF(pair);

`

469

472

`return -1;

`

470

473

` }

`

``

474

`+

#if defined(X86_64)

`

``

475

`+

if (PyCArrayTypeObject_Check(desc))

`

``

476

`+

arrays_seen = 1;

`

``

477

`+

#endif

`

471

478

`dict = PyType_stgdict(desc);

`

472

479

`if (dict == NULL) {

`

473

480

`Py_DECREF(pair);

`

`@@ -608,6 +615,106 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct

`

608

615

`stgdict->align = total_align;

`

609

616

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

`

610

617

``

``

618

`+

#if defined(X86_64)

`

``

619

+

``

620

`+

#define MAX_ELEMENTS 16

`

``

621

+

``

622

`+

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

`

``

623

`+

/*

`

``

624

`+

`

``

625

`+

`

``

626

`+

`

``

627

`+

`

``

628

`+

`

``

629

`+

`

``

630

`+

`

``

631

`+

`

``

632

`+

`

``

633

`+

`

``

634

`+

`

``

635

`+

`

``

636

`+

`

``

637

`+

`

``

638

`+

`

``

639

`+

*/

`

``

640

`+

ffi_type *actual_types[MAX_ELEMENTS + 1];

`

``

641

`+

int actual_type_index = 0;

`

``

642

+

``

643

`+

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

`

``

644

`+

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

`

``

645

`+

PyObject *name, *desc;

`

``

646

`+

PyObject *pair = PySequence_GetItem(fields, i);

`

``

647

`+

StgDictObject *dict;

`

``

648

`+

int bitsize = 0;

`

``

649

+

``

650

`+

if (pair == NULL) {

`

``

651

`+

return -1;

`

``

652

`+

}

`

``

653

`+

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

`

``

654

`+

PyErr_SetString(PyExc_TypeError,

`

``

655

`+

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

`

``

656

`+

Py_XDECREF(pair);

`

``

657

`+

return -1;

`

``

658

`+

}

`

``

659

`+

dict = PyType_stgdict(desc);

`

``

660

`+

if (dict == NULL) {

`

``

661

`+

Py_DECREF(pair);

`

``

662

`+

PyErr_Format(PyExc_TypeError,

`

``

663

`+

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

`

``

664

`+

i);

`

``

665

`+

return -1;

`

``

666

`+

}

`

``

667

`+

if (!PyCArrayTypeObject_Check(desc)) {

`

``

668

`+

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

`

``

669

`+

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

`

``

670

`+

assert(actual_type_index <= MAX_ELEMENTS);

`

``

671

`+

}

`

``

672

`+

else {

`

``

673

`+

int length = dict->length;

`

``

674

`+

StgDictObject *edict;

`

``

675

+

``

676

`+

edict = PyType_stgdict(dict->proto);

`

``

677

`+

if (edict == NULL) {

`

``

678

`+

Py_DECREF(pair);

`

``

679

`+

PyErr_Format(PyExc_TypeError,

`

``

680

`+

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

`

``

681

`+

i);

`

``

682

`+

return -1;

`

``

683

`+

}

`

``

684

`+

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

`

``

685

`+

while (length > 0) {

`

``

686

`+

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

`

``

687

`+

assert(actual_type_index <= MAX_ELEMENTS);

`

``

688

`+

length--;

`

``

689

`+

}

`

``

690

`+

}

`

``

691

`+

Py_DECREF(pair);

`

``

692

`+

}

`

``

693

+

``

694

`+

actual_types[actual_type_index++] = NULL;

`

``

695

`+

/*

`

``

696

`+

`

``

697

`+

`

``

698

`+

*/

`

``

699

`+

assert(stgdict->ffi_type_pointer.elements);

`

``

700

`+

PyMem_Free(stgdict->ffi_type_pointer.elements);

`

``

701

`+

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

`

``

702

`+

ffi_ofs + actual_type_index);

`

``

703

`+

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

`

``

704

`+

PyErr_NoMemory();

`

``

705

`+

return -1;

`

``

706

`+

}

`

``

707

`+

if (ffi_ofs) {

`

``

708

`+

memcpy(stgdict->ffi_type_pointer.elements,

`

``

709

`+

basedict->ffi_type_pointer.elements,

`

``

710

`+

ffi_ofs * sizeof(ffi_type *));

`

``

711

+

``

712

`+

}

`

``

713

`+

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

`

``

714

`+

actual_type_index * sizeof(ffi_type *));

`

``

715

`+

}

`

``

716

`+

#endif

`

``

717

+

611

718

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

`

612

719

` have been set until now. */

`

613

720

`if (stgdict->flags & DICTFLAG_FINAL) {

`