> The difference is that with signed integers, your sanity check is simple and always the same and requires no thought for edge cases: `if(index < 0 || index > max)`

Wait, what? How is that easier than `if (index > max)`?

Because if max is a calculated value, it could silently wrap around and leave index to cause a buffer overflow.

Or if index is counting down, a calculated index could silently wrap around and cause the same issue.

And if both are calculated and wrap around, you'll have fun debugging spooky action at a distance!

If both are signed, that won't happen. You probably do have a bug if max or index is calculated to a negative value, but it's likely not an exploitable one.

I have no clue what cases you have in mind, can you give some examples? Surely when you have index as unsigned the maximum would be represented unsigned as well?