5 ms·
Gavin, there is no point in arguing with fanatics. (You have to know that none of them are actually going to dive into your code and possibly learn something ne
by diffxx 4y ago
Gavin, there is no point in arguing with fanatics. (You have to know that none of them are actually going to dive into your code and possibly learn something new that didn't come from a vetted authority figure). They are incapable of listening to their own independent thoughts, assuming that they have them, and must attack anyone who counters their dogma because it risks shattering their core beliefs, which is intolerable. The funny thing is that the truth of rust is right there in its name. It is a corrosive process that ruins the iron that it touches.
- stouset 4y agoI really like C. I did actually spend about an hour reading his code. It's very nice, and I genuinely believe that Gavin is probably capable of writing memory-safe C most of the time. Except when his sanitizer setup is accidentally disabled, of course. I did find at least one case where a function in isolation is explicitly not memory-safe, but its safety depends on implicit and undocumented assumptions about how it's called. I didn't find a way to exploit it from the userland program. In `bc_parse_addNum`[1], a `char *` string is indexed into without checking the length. Callers are expected to provide strings of at least length 2. That expectation is not documented, though it is adhered to. But it is a landmine waiting to be tripped over should that assumption change. But this is a sideshow. Experts have been insisting for decades that they can write crash-free C and yet we continue to regularly find exploitable memory issues in every large multi-author C project. It's plain as day that—for almost all of us—an increasingly indefensible amount of the time spent on C programs is in dealing with the types of bugs that languages like Rust prevent outright. Whether that's simply finding and fixing them, architecting programs to avoid them, incorporating those fixes into downstream projects, mitigating their impact in live production systems, or whatever, our industry pays an enormous ongoing cost. Even in projects that have never had a public release with a memory bug, significant engineering time is spent on them just during development iteration. As a handy example, the Linux kernel is still trying to rid itself of `strlcpy`[2] which has been the source of multiple CVEs. This process has taken upwards of twenty years. And that's after spending god knows how much time and effort migrating to `strlcpy` from `strcpy` in the first place. [1] https://git.yzena.com/gavin/bc/src/branch/master/src/parse.c#L98 https://git.yzena.com/gavin/bc/src/branch/master/src/parse.c... [2] https://lwn.net/Articles/905777/ https://lwn.net/Articles/905777/
- gavinhoward 4y ago> I really like C. I did actually spend about an hour reading his code. It's very nice, and I genuinely believe that Gavin is probably capable of writing memory-safe C most of the time. This is a nice compliment, thank you. > Except when his sanitizer setup is accidentally disabled, of course. Fair criticism. XD > I did find at least one case where a function in isolation is explicitly not memory-safe, but its safety depends on implicit and undocumented assumptions about how it's called. I didn't find a way to exploit it from the userland program. In `bc_parse_addNum`[1], a `char` pointer string is indexed into without checking the length. Callers are expected to provide strings of at least length 2. That expectation is not documented, though it is adhered to. But it is a landmine waiting to be tripped over should that assumption change. Callers are actually required to pass a string of length 1 including the nul terminator, but you are correct, this assumption is not documented in `bc_parse_addNum()`, and it should be. By the way, `bc_parse_zero` and bc_parse_one` are constants, so I can make assumptions about them. This is why an empty string is fine: those constants do not have nul terminators at index 0, so if the string parameter does, the short-circuit operators will short-circuit. I've pushed commit e4b31620f181 to document that assumption, along with a note that assuming a non-empty string might be useful too. > But this is a sideshow. Experts have been insisting for decades that they can write crash-free C and yet we continue to regularly find exploitable memory issues in every large multi-author C project. It's plain as day that—for almost all of us—an increasingly indefensible amount of the time spent on C programs is in dealing with the types of bugs that languages like Rust prevent outright. Whether that's simply finding and fixing them, architecting programs to avoid them, incorporating those fixes into downstream projects, mitigating their impact in live production systems, or whatever, our industry pays an enormous ongoing cost. Even in projects that have never had a public release with a memory bug, significant engineering time is spent on them just during development iteration. I agree with this. I never said people should use C by default; absolutely not. They should use Rust by default. But as I said in another of my comments [1], I think I personally would write buggier code in Rust than in C. [1]: https://news.ycombinator.com/item?id=32915468 https://news.ycombinator.com/item?id=32915468
- stouset 4y ago> I've pushed commit e4b31620f181 to document that assumption, along with a note that assuming a non-empty string might be useful too. Nice! > By the way, `bc_parse_zero` and bc_parse_one` are constants, so I can make assumptions about them. This is why an empty string is fine: those constants do not have nul terminators at index 0, so if the string parameter does, the short-circuit operators will short-circuit. Ah, of course. I knew that they were constants, but I didn't consider the short-circuiting of the comparison before indexing further into the string. > But as I said in another of my comments [1], I think I personally would write buggier code in Rust than in C. I hope you understand that—all snark aside—I truly, genuinely believe you. I do suspect that if you had invested the just time you've spent figuring out how to work around C's memory-safety shortcomings, your proficiency would be within spitting distance. But obviously those costs are already sunk. And at the end of the day, if you just love C and only want to write C then it doesn't matter what sorts of things another language provides. I love C, but I've also come to love Rust. Sum types and exhaustive pattern matching are the sorts of things that are hard to live without once you've had them, and now languages that don't offer them are pretty much ruined for me. But at the same time I'm not a fan of the async/await paradigm, though I begrudgingly understand why it was necessary and why it was designed the way it was. For now I simply avoid it, but it makes me sad that we were never able to find something better.