Too bad segmentation was dropped for 64-bit code on x86, leaving just page tables. 32-bit x86 retains the segmentation model of the 286, extending it to 32 bits, and making it work with virtual addresses instead of physical addresses if the paging system is also enabled.
Most 32-bit operating systems ignored the segmentation system, basically just running everything in what the old timers would call "small model".
If we had segmentation in 64-bit mode, then I wonder if we could defend against a lot of these problems by running things we want to sandbox, such as JavaScript, in a different segment that only has access to the upper end of our virtual address space?
As long as the sandboxed code cannot change the segment registers, this would prevent it from generating an address outside the sandboxed portion of the processes' virtual address space.
I don't recall if the x86 segment system provides a way to trap attempts to change a segment register. If I recall correctly, it does support more than just the two level kernel/user protection system, and I think it supports not allowing loading a segment register with a selector that refers to a segment belonging to a higher level, so maybe if user mode was split into two levels, so sandboxed code could be run at a less privileged level than the main process it could work.
In general, I think processor designers need to take into account the need for processes to run sandboxed code, and provide some kind of mechanism the processes can use to protect themselves from malicious code in the sandbox.