Assignment operation in Delphi are not thread safe. If you have one thread writing and other threads reading, such access must be protected or you will get crashes or buggy behavior.
You can safely write and read 32bit aligned simple types, in terms that such code will not cause any crashing, but such code will also not work as intended, unless you don't care about actual values stored.
So, weak references in Delphi are not thread safe. Also even strong interface references in Delphi are not thread safe. So there is no bug here, just bad test case.
Excerpt from my book Delphi Event-based and Asynchronous Programming (Part 5. Thread Safety)
If you have multiple threads accessing - reading and writing - the same
reference, one thread can easily interfere with the other. Let's say we have a
shared interface reference `Data`, pointing to a previously created object, one
thread that sets that reference to nil, and another thread that tries to take
another strong reference from that one with an assignment to another variable
`Tmp`. The first thread will execute the `_IntfClear` function that will result in
object destruction. The second thread, trying to grab a strong reference
preventing object destruction, will execute the `_IntfCopy` function:
var
Data, Tmp: IInterface;
Data := nil; // Thread 1 -> _IntfClear
Tmp := Data; // Thread 2 -> _IntfCopy
If the `Source._AddRef` line from the `_IntfCopy` function executes before the
call to `IInterface(P)._Release` manages to decrease the reference count to zero
and subsequently calls the object's destructor, all is good. The second thread
will successfully capture another strong reference to the object instance.
However, the first thread can interrupt the second thread at the wrong moment,
just after the `Source <> nil` check was successfully passed, but before
`Source._AddRef` had the chance to increment the object's reference count. In
that case, the first thread will happily destroy the object instance while the
second thread will happily grab a strong reference to an already nuked object, and
you can forget about happily ever after.
Note: Besides interface references to objects, the reference counting mechanism
is also used for other types like strings and dynamic arrays. Assignment of
those types is also not thread-safe.