Reading from the zero page is legal, that doesn’t cause it to crash. The crash is because of a logic “bug” in the program where the zero it reads back causes some other issue in the program.
I say “bug” because it’s clearly impossible without the kernel messing up. It just stored a non-zero value there.
What happens here is a bug in munmap() that happens in another thread. It corrupts the TLB, for a brief instant replacing the correct page.
So that the virtual memory page that the crashed thread tried to read its RAM, it gets replaced by the special zero-filled physical page. The kernel uses this zero page as an optimization when it needs to create a region of data filled with zeroes, so it can just map one physical page over the entire range.
It's a really low-level bug that just requires a lot of specialized knowledge just to explain. A better write-up is certainly possible but needs to have a lot of explanations to make it understandable.