Skip to content

Commit deac31d

Browse files
authored
gh-111178: fix UBSan failures in Modules/overlapped.c (GH-129786)
Fix UBSan failures for `OverlappedObject`
1 parent 4466e91 commit deac31d

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

Modules/overlapped.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ typedef struct {
124124
};
125125
} OverlappedObject;
126126

127+
#define OverlappedObject_CAST(op) ((OverlappedObject *)(op))
128+
127129

128130
static inline void
129131
steal_buffer(Py_buffer * dst, Py_buffer * src)
@@ -666,8 +668,14 @@ _overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event)
666668

667669

668670
/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
669-
buffers while overlapped are still running, to prevent a crash. */
670-
static int
671+
* buffers while overlapped are still running, to prevent a crash.
672+
*
673+
* Note (gh-111178): Since OverlappedType.tp_clear is not used, we do not
674+
* need to prevent an undefined behaviour by changing the type of 'self'.
675+
* To avoid suppressing unused return values, we however make this function
676+
* return nothing instead of 0, as we never use it.
677+
*/
678+
static void
671679
Overlapped_clear(OverlappedObject *self)
672680
{
673681
switch (self->type) {
@@ -709,16 +717,16 @@ Overlapped_clear(OverlappedObject *self)
709717
}
710718
}
711719
self->type = TYPE_NOT_STARTED;
712-
return 0;
713720
}
714721

715722
static void
716-
Overlapped_dealloc(OverlappedObject *self)
723+
Overlapped_dealloc(PyObject *op)
717724
{
718725
DWORD bytes;
719726
DWORD olderr = GetLastError();
720727
BOOL wait = FALSE;
721728
BOOL ret;
729+
OverlappedObject *self = OverlappedObject_CAST(op);
722730

723731
if (!HasOverlappedIoCompleted(&self->overlapped) &&
724732
self->type != TYPE_NOT_STARTED)
@@ -1642,21 +1650,24 @@ _overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self,
16421650
}
16431651

16441652
static PyObject*
1645-
Overlapped_getaddress(OverlappedObject *self)
1653+
Overlapped_getaddress(PyObject *op, void *Py_UNUSED(closure))
16461654
{
1655+
OverlappedObject *self = OverlappedObject_CAST(op);
16471656
return PyLong_FromVoidPtr(&self->overlapped);
16481657
}
16491658

16501659
static PyObject*
1651-
Overlapped_getpending(OverlappedObject *self)
1660+
Overlapped_getpending(PyObject *op, void *Py_UNUSED(closure))
16521661
{
1662+
OverlappedObject *self = OverlappedObject_CAST(op);
16531663
return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
16541664
self->type != TYPE_NOT_STARTED);
16551665
}
16561666

16571667
static int
1658-
Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
1668+
Overlapped_traverse(PyObject *op, visitproc visit, void *arg)
16591669
{
1670+
OverlappedObject *self = OverlappedObject_CAST(op);
16601671
switch (self->type) {
16611672
case TYPE_READ:
16621673
case TYPE_ACCEPT:
@@ -1976,9 +1987,9 @@ static PyMemberDef Overlapped_members[] = {
19761987
};
19771988

19781989
static PyGetSetDef Overlapped_getsets[] = {
1979-
{"address", (getter)Overlapped_getaddress, NULL,
1990+
{"address", Overlapped_getaddress, NULL,
19801991
"Address of overlapped structure"},
1981-
{"pending", (getter)Overlapped_getpending, NULL,
1992+
{"pending", Overlapped_getpending, NULL,
19821993
"Whether the operation is pending"},
19831994
{NULL},
19841995
};

0 commit comments

Comments
 (0)