__contains__ on an incompletely evaluated QuerySet can incorrectly return False
|Reported by:||kmichel_wgs||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.4|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||yes||Patch needs improvement:||no|
The bug is in the function QuerySet.__contains__(self, val), which is executed when using the python operator in.
It can only happen if :
- val is in the QuerySet
- val is the last item of the QuerySet
- the QuerySet has not been completely evaluated
If all those conditions hold, then :
- val is not yet in self._result_cache
- self._iter is not None
This makes us jump to the while True loop, which runs correctly until we fetch the last item using self._fill_cache(num=1).
When fetching the last item, inside the self._fill_cache function, self._iter is set to None.
Just after fetching the last item, but before comparing its value against val, self.__contains__ checks the value of self._iter, which is None, and incorrectly return False.
The value of the last item should have been checked before checking the value of self._iter.
Change History (4)
Changed 3 years ago by kmichel_wgs
comment:1 Changed 3 years ago by ogier
- Needs documentation unset
- Needs tests set
- Patch needs improvement unset
- Triage Stage changed from Unreviewed to Accepted