4 ms·
Not really. Safe code generating unsafe-code-with-bugs gets you a vulnerable program, so rewriting Ragel in Rust doesn't help. As to generating Rust - Rust is
by JoachimSchipper 10y ago
Not really.
Safe code generating unsafe-code-with-bugs gets you a vulnerable program, so rewriting Ragel in Rust doesn't help.
As to generating Rust - Rust isn't magic, and Rust-that-is-as-fast-as-C can't do a lot more work than C. In particular, you don't want to do memory allocation in the fast path of a network server written for performance (note that Rust uses jemalloc, which is a C memory allocation library; Rust memory allocation isn't going to beat C memory allocation.)
As such, a realistic Rust program probably needs to re-use network buffers, at which point language-level security doesn't stop you from sending out "old" data that was still in the buffer. [EDIT: but see the reply https://news.ycombinator.com/item?id=13804831 https://news.ycombinator.com/item?id=13804831 below.] A debug build in Rust could allocate-per-request and detect the problem; but allocate-per-request in C is also likely to detect such overflows (indeed, the CloudFlare server did occasionally crash on this bug), and C programmers can also use e.g. VALGRIND_MAKE_MEM_UNDEFINED() for effort comparable to maintaining an alternate allocate-per-request implementation in Rust.
The difference for the fast path - where Rust can't do a lot more work, and where you can focus your effort - just isn't very large. (Using a safe language for e.g. low-performance control-plane interfaces can help, however - but at that point, you may well be arguing e.g. Rust vs. Lua.)
- Manishearth 10y agoRust's version of Ragel actually generates 100% safe Rust code, AFAICT without any additional cost. http://github.com/erickt/stateful http://github.com/erickt/stateful
- JoachimSchipper 10y agoAre you sure? CloudFlare's problem seems to have been running off the end of a logical buffer embedded in a linked list of "physical" buffers. (Sorry, have to run - will try to take a better look later tonight.)
- Manishearth 10y agoIn Rust you'd usually use a slice for this anyway, which has bounds checks. Yes, you could use indices instead, but that's not very Rusty (and more annoying to use!), whereas using pointer arithmetic is par for C. Edit: Yes, you could ultimately get it wrong in Rust, too, I just think it's much less likely.
- JoachimSchipper 10y agoSo you're thinking of an iterator of slices of char (arrays), right? It still somewhat tricky to get right to me; the writer wants to have access to the underlying physical buffers, so you need a conversion step from list-of-physical-buffers without allocating, etc. But you're probably not wrong that a Rust programmer is more likely to get this right; thanks! (And it's all likelihoods anyway; there's plenty of C code that doesn't get this wrong, and e.g. the VALGRIND_MAKE_MEM_UNDEFINED() I suggested above does reliably - albeit dynamically - find this problem in C.) (Added a reference from my top comment to your reply.)
- Manishearth 10y agoYou don't need to allocate, Rust slices are safe zero-copy views into an existing buffer. Yes, you can run under valgrind, but dynamic checks ... :) You need to have testcases that hits those code paths, and it's really hard to make "unexpected" testcases that test code paths like these. That's why fuzzing is awesome!
- deleted 10y ago[deleted]
- deleted 10y ago[deleted]
- Scaevolus 10y agoBounds checking slices makes code around 1% slower. It's worth it, but not free.
- Manishearth 10y agoI mean, that was the fix in this situation too, anyway. "free" depends on what you're comparing it to.