Case in point: You can make the same error in Java (I think it's even included in the docs for Comparators that you shouldn't do a-b, because of integer overflow/underflow), but it cannot lead to an out-of-bounds read/write. And that's because Java (~glibc) handles the comparison function that you give it differently.
For instance, the bad comparator could be used in nested authentication checks:
if check_A { drop privilege to FOO } else if check_B { drop privilege to BAR } else { /* leave root bit set, because "not (A or B)" means root */ }
and it could lead to a privilege escalation in the face of malformed inputs.
I've seen this sort of thing happen in the wild with Java.
The closes thing there is 7.22.5.2 §4: "If two elements compare as equal, their order in the resulting sorted array is unspecified"
So I'd say blaming users for a bug in glibc isn't fair.
"When the same objects (consisting of size bytes, irrespective of their current positions in the array) are passed more than once to the comparison function, the results shall be consistent with one another. That is, for qsort they shall define a total ordering on the array, and for bsearch the same object shall always compare the same way with the key."
I'm sure there are some Rust devs who would say the same thing about C. It's possible to write secure code in C, just as it's possible to write a sort with defined behavior using glibc.