5 ms·
Huge. Only checking array bounds on every access degrades performance considerably. But I am waiting for the Rust-OS to complete -- if one is under constructio
by habibur 5y ago
Huge. Only checking array bounds on every access degrades performance considerably.
But I am waiting for the Rust-OS to complete -- if one is under construction now. We can check how that stands when released.
- fabianhjr 5y agoAFAIK RedoxOS has been bootable for a while now. (Though, a very simple new OS) https://www.redox-os.org/ https://www.redox-os.org/
- deleted 5y ago[deleted]
- throwaway81523 5y ago> Huge. Only checking array bounds on every access degrades performance considerably. I have not found this, at least in application code. There is usually at most a few percent different between v[i] and v.at(i) (the latter checks bounds) with C++ std::vector, for example. So I almost always use .at() these days, and it does catch bugs.
- gpderetta 5y agowouldn't compiling with _GLIBCXX_ASSERTIONS or the corresponding for your compiler of choice be a better solution? It will also catch quite a few more issues (dereferencing null smart pointers, empty optionals, etc.), while being still relatively lightweight.
- pjmlp 5y agoNot the OP, that is my approach, keep on the bounds checking settings from VC++ also in release builds. And before STL was a thing, all the custom types I had were bounds checked by default.
- throwaway81523 5y agoThanks, I didn't know (or didn't remember) about this, but it's not clear from the docs that it bounds checks []. I don't find it difficult to use .at(). I'll try the debug mode too, but when I bother writing something in C++ it's usually because I actually care about its speed, so I don't want the overhead to be too bad. https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros...
- scns 5y agoWell, there is the rub. The safe thing to do is more verbose, the unsafe way is in muscle memory. Rust did it the other way around deliberately. But that is easy if you do a new design and don't need to retrofit a safe solution. No snark intended.
- pjmlp 5y agoThat is why one should always enable the compiler switches that turn operator[]() into at(), and then only disable them on case by case scenario, if proven worthwhile to do so.
- volta83 5y ago> Huge. Only checking array bounds on every access degrades performance considerably. Citation needed, since all evidence points to the contrary. Could you please point us to a Rust application (there are hundreds of thousands at this point) that gets noticeably faster when disabling bound checks? In servo, a whole web browser written in Rust, the cost of doing this was negligible, to the point that it was barely measurable (1-3%, noise levels for such a big app). Same for Firefox which has a substantial amount of Rust. Go ahead and give Fuchsia a try. You can enable bound checks for a substantial part of Android's user space and not really notice it. Same for Redox, or any operating system kernel written in Rust. You have many large applications to choose from, so please, just point us to 1 for which this is the case. --- Compared with other mitigations already in the kernel, that can cost you up to 50% perf, and that people seem to be ok with, bound checking all the array accesses seems like a no brainer, given that ~70% of CVE are caused by memory issues. When most people think about bound checking all array accesses, they think, for some "i can only think inside the box" reason, that this happens on hardware, for every memory access. But that is not how Rust works. Rust adds bound checks "in Rust", and the Rust compiler and LLVM are really good at removing duplicates, hoisting many bound checks out of a loop into a single bound check at the beginning of the loop, etc. People also think that this is an all or nothing approach, but Rust allows you to manually access without bound checks and do the hoisting manually. So if you find a function in which this makes a big difference, you can just fix the performance issue there manually.
- tialaramex 5y agoFor the optimisation, the compiler will even reason that e.g. iterating over the vector necessarily involves knowing the size of the vector and stopping before the end, so it doesn't need to add the bounds check at all because that's redundant. This is easier in Rust because the compiler knows nobody else can be mutating this vector while you're iterating over it - that's forbidden in the language. So, in general, the idiomatic Rust "twiddle all these doodads" compiles to the same machine code as the idiomatic C++ for that problem, even though Rust bounds checked it and C++ didn't care. Lots of Rust checks are like this, they compile away to nothing, so long as what you did is necessarily correct. The Option<NonZeroU64> stuff a few days ago is another example. Same machine code as a C++ long integer using zero as a signal value, but with type safety.
- pjmlp 5y agoI have used C++ since 1993 with bounds checking enabled, it hardly has ever mattered. The very few cases where it actually mattered for project delivery acceptance, were proven with a profiler, and fixed on those single cases only. Most of the time it is just cargo cult taken from C into other languages. Multics had a better DoD security profile assessment than UNIX, thanks to PL/I being bounds checked by default. Mac OS used Object Pascal until they decided to switch to C++ around 1992, it also hardly impacted their sales, using a language with bounds checking.