[New-bugs-announce] [issue32734] Asyncio Lock safety issue (unlimited acquire)
report at bugs.python.org
Wed Jan 31 13:55:45 EST 2018
New submission from Bar Harel <bzvi7919 at gmail.com>:
I found a pretty dangerous bug that allows acquiring locks in asyncio without them being free.
This happens due to double release (calling _wake_up_first) from both release and acquire in case of cancellation.
The example I've uploaded exploits it by acquiring 4 times, which grooms the loop's _ready queue, cancelling the second acquire to add the cancellation to the _ready queue, and releasing once to add the next waiter (number 3) to the _ready queue. Next event loop step causes the cancellation to run first, skipping the queued waiter (due to .done check being true) and waking the next waiter in line (number 4). Then both number 3 and number 4 run together on the same Lock.
I'm not at home so it's hard for me to code but the simple way of fixing it is by adding this line - "if self._locked: yield from self.acquire()" after the "yield from fut" (quite minimal overhead and only if bug happens, so no harm) or by slightly restructuring the code and the checks regarding cancelled futures.
I can later on post the restructured code but I think the simple if statement is a pretty fine and efficient fix.
nosy: asvetlov, bar.harel, yselivanov
title: Asyncio Lock safety issue (unlimited acquire)
versions: Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8
Added file: https://bugs.python.org/file47419/bug.py
Python tracker <report at bugs.python.org>
More information about the New-bugs-announce