Skip to content

list's rich comparison has a race condition for non-trivial __eq__ and may return an incorrect result #148442

Closed

Description

@KowalskiThomas

Bug report

I found a race condition happening in the rich comparison function for list where calling a rich comparison on items, which may release the GIL, may result in the list being mutated and the wrong items being compared later on in list's rich comparison.

The current code iterates through the list's ob_item to find the index of the first non-equal objects. It then calls PyObject_RichCompareBool on the two objects (which may call user-defined Python code, which may release the GIL), then checks whether the rich comparison said the items were different.
At this point, what the items exactly were is forgotten (vitem and witem go out of scope).

Later in the rich comparison function, if the desired comparison operation is not EQ/NEQ, a new call to PyObject_RichCompare is made to know which is larger/smaller. To do this, vitem and witem are re-read from the ob_item, but ob_item may actually have changed in the meantime, meaning the return value may be incorrect.

This is in a way similar to my other issue #148259 -- the root cause is mostly the same (re-reading a previously-read value that may have changed in the meantime).

I have a branch with a proposed fix, although there may be a better way as this one requires to add a lot of refcount changes which makes it all a bit hard to read / do bookkeeping for.

Note I don't currently have a reproducer, but I may try to make one if needed.

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Activity

  1. colesbury commented on Apr 13, 2026

    @colesbury
    Contributor

    I think your proposed fix makes sense here. I just have some minor comments about code structure: I think it'll be easier to read if you lift the logic for if (!k) { ... } into that block instead of breaking out of the loop.

  2. KowalskiThomas commented on Apr 13, 2026

    @KowalskiThomas
    ContributorAuthor

    Noted! I'll give it a look when I get a chance.

  3. KowalskiThomas commented on Apr 30, 2026

    @KowalskiThomas
    ContributorAuthor

    @colesbury Sorry for the slight delay here, I changed what you mentioned on #148531 and should be ready for review now!

  4. added a commit that references this issue on Aug 30, 2026
  5. serhiy-storchaka commented on Aug 30, 2026

    @serhiy-storchaka
    Member

    Thank you for your contribution, @KowalskiThomas. Merged in main only. This is too large change, and while it makes some cases more correct, it cannot fix all cases. For example, if already compared elements were mutated during comparing the following elements, we can still get wrong result.

  6. added a commit that references this issue on Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.16new features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions