On 2024-10-24 at 20:54:53 +0100, MRAB via Python-list <python-list@python.org> wrote:
> On 2024-10-24 20:21, Left Right wrote: > > > > > The stack is created on line 760 with os.lstat and entries are > > > > > appended > > > > > on lines 677 (os.rmdir), 679 (os.close) and 689 (os.lstat). > > > > > > > > > > 'func' is popped off the stack on line 651 and check in the following > > > > > lines. > > > > > > > > > > I can't see anywhere else where something else is put onto the stack > > > > > or > > > > > an entry is replaced. > > > > But the _rmtree_safe_fd() compares func to a *dynamically* resolved > > reference: os.lstat. If the reference to os changed (or os object was > > modified to have new reference at lstat) between the time os.lstat was > > added to the stack and the time of comparison, then comparison > > would've failed. To illustrate my idea: > > > > os.lstat = lambda x: x # thread 1 > > stack.append((os.lstat, ...)) # thread 1 > > os.lstat = lambda x: x # thread 2 > > func, *_ = stack.pop() # thread 1 > > assert func is os.lstat # thread 1 (failure!) > > > > The only question is: is it possible to modify os.lstat like that, and > > if so, how? > > > > Other alternatives include a malfunctioning "is" operator, > > malfunctioning module cache... all those are a lot less likely. > What is the probability of replacing os.lstat, os.close or os.rmdir from > another thread at just the right time? That is never the right question in a multi-threaded system. The answer is always that is doesn't matter, the odds will beat you in the end. Or sometimes right in the middle of a CPU instruction; does anyone remember the MC680XX series? Yes, as a matter of fact, I did used to make my living designing, building, delivering, and maintaining such systems. -- https://mail.python.org/mailman/listinfo/python-list