8 ms·
I am more paranoid and cautious than, say, 95% of the programmers I've known. Maybe more. I still don't trust myself to write safe C. Specifically, I do not th
by ekidd 4y ago
I am more paranoid and cautious than, say, 95% of the programmers I've known. Maybe more. I still don't trust myself to write safe C.
Specifically, I do not think I'm smart enough to violate the Chrome team's Rule of 2: https://chromium.googlesource.com/chromium/src/+/master/docs/security/rule-of-2.md https://chromium.googlesource.com/chromium/src/+/master/docs...
> The Rule Of 2 is: Pick no more than 2 of untrustworthy inputs; unsafe implementation language; and high privilege.
I do know of a few C programmers I'd trust: DJB, many of the OpenBSD team, the Dovecot maintainers, and a few others with long track records of security.
But I don't trust myself because I've used fuzzers on my Rust code, trying billions of inputs. And I've found DDOS bugs that would have been potential exploits in C.
What's more damning, the most careful C code I ever wrote has an enormous, sneaky test suite. It was tested with every sanitizer I could find. It used carefully designed error handling conventions. Still, in the last 20 years, it has been the subject of several CVEs. You see, I relied on a high-quality 3rd party XML parser, and that parser had a handful of bugs.
Out of 7 billion people on this planet, the number that I'd personally trust to reliaby write CVE-free C code is in the low triple digits. I'm not one of them.
Understanding Rust is a cakewalk compared to understanding "undefined behavior" in the C standard, or to making sure a large C program never overflows an addition, or accesses memory out of bounds. But Rust is not the only option. Use Go or Java or Ada SPARK or a functional language or WUFFS. Any are fine.
As an industry, we need to stop making the same endless security mistakes. It's not OK.
- delusional 4y ago> You see, I relied on a high-quality 3rd party XML parser, and that parser had a handful of bugs. At that point it's hardly the fault of C. Even in supposedly "memory safe" languages like Java, XML (and json) parsers are often riddled with bugs and design problems that can be exploited for remote execution. It's a joke, but these parsers are still somehow considered "best in class" because many supposed "programmers" are willing to trade security for the ability to write annotations. I'd say that what you describe in your software is exactly what i like about C. You know it's dangerous, so you take precautions. You then discover that those precautions maybe aren't enough and you go looking for something more stringent (like rust). There's learning there. If we cargo cult Rust as "what people should learn instead of C because it's secure" bad programmers will go write poorly designed rust code that's as unsafe (if not more so) as any C code, except now they won't be careful because "the language is safe".
- kajaktum 4y ago>I'd say that what you describe in your software is exactly what i like about C. You know it's dangerous, so you take precautions. You then discover that those precautions maybe aren't enough and you go looking for something more stringent (like rust). There's learning there. If we cargo cult Rust as "what people should learn instead of C because it's secure" bad programmers will go write poorly designed rust code that's as unsafe (if not more so) as any C code, except now they won't be careful because "the language is safe". What level of cope is this? "Bad language is better because we know its bad so we become better!" Every time someone argues for C or C++ I replace them with assembly and C respectively. The argument makes about the same amount of sense.
- lumb63 4y agoI don’t think that’s what they’re saying. They’re saying that there is utility in understanding what you’re getting with a memory-safe language like Rust. Why would a programmer care if they’re getting memory safety and thread safety if they don’t know what unsafeness looks like? It’s the same reason we teach history in school; knowing where we came from gives us a better perspective of where we are today.
- avgcorrection 4y agoThey can read the Rustonomicon. Done. They can also write C or Unsafe Rust in order to learn about what regular Rust gives them. But none of that is an argument for learning C and then stumbling into a safer language after doing that, since then you have to learn (say) Rust as well as unlearn your C (or whatever unsafe language habits) as well.[1] [1] https://www.reddit.com/r/rust/comments/10rnymj/my_reaction_to_dr_stroustrups_recent_memory/j6ydjso/ https://www.reddit.com/r/rust/comments/10rnymj/my_reaction_t...
- kajaktum 4y ago>It’s the same reason we teach history in school; knowing where we came from gives us a better perspective of where we are today. What we learn from history is mostly "holy shit that was fucking awful thank god we stopped doing that!". Except for programmers it seems. I have no objection to learning or using C but we don't ride horse caravans around anymore.
- UncleMeat 4y agoEven people like DJB have written buffer overrun vulns in their C code. In my opinion, it is impossible for an organization of meaningful size to write and maintain a program of meaningful complexity over a period of time in C or C++ (rather than some very strongly constrained version of C++ or a constrained and augmented version of C) without introducing memory safety errors.
- naasking 4y agoI mostly agree, but I also feel it hasn't really been attempted properly, by which I mean exploiting the type checker to its fullest. For instance, write a stdlib where all functions reading input return "unsanitized" data types that must be supplied with a validation check before the sanitized value can be read out. Safer strings and arrays, possibly references instead of pointers, return explicit error values rather than errno, etc. And then require a program to only write against the safelib. I suspect most C programmers just wouldn't like the constraints, or would be concerned with performance degradation, and that's the real problem. Edit: another avenue is to also use Frama-C to check your code.
- UncleMeat 4y agoYou can do this. You can ban all pointer arithmetic, use array types that have attached sizes and automatically introduce bounds checks, require various compiler extensions and annotations for lifetimes, require initialization immediately upon declaration, have the compiler introduce nullptr checks when it cannot prove a pointer is nonnull, ban std::variant and reinterpret_cast<T>, and more. You end up with something that resembles the set of programming requirements from Rust (if you leverage lifetime annotations) or you end up with something resembling a refcounting GC (if you demand the use of shared_ptr everywhere). This cannot really be "attempted properly" at scale. To implement this with C you need to both superset and subset the language. To implement this with C++ you need to harshly subset the language. Both communities hold backwards compatibility as a huge goal, making it impossible to move in this direction. A project like Carbon seeks to incrementally move in this direction, but required breaking off from the C++ community. Projects like Rust just rip the band-aid off entirely at the beginning. The "don't worry, C is fine if you just don't suck at programming" folks don't tend to push for these extreme changes.
- zajio1am 4y ago> or to making sure a large C program never overflows an addition Does Rust help with integer overflows? AFAIK it is as unsafe as C w.r.t. that.
- the_mitsuhiko 4y agoIt has controllable behavior, explicit APIs to pick the precise behavior and there is no undefined behavior with regards to overflows which greatly helps with memory safety.
- zajio1am 4y agoIt is controllable in real C compilers too (i.e. -fwrapv, -ftrapv GCC options), so you can make them silently ignored or cause trap. Real problem with integer overflows is that they are logic errors that are hard to check in compile-time, and neither C nor Rust helps with preventing them.
- the_mitsuhiko 4y agoI’m not sure that’s true but I also don’t have data on this. In my personal experience the issue with integer over-/underflows mostly played a role when those integers were used in branching or memory indexing. The rules around UB with overflows are really messy and those issues definitely do not exist in Rust.
- celrod 4y agoIt checks in debug mode, but these checks are turned off in release mode by default. They can be turned on in release mode, but C/C++ could add `-ftrapv` too[0]... You also have access to `checked_mul` and friends, so manually writing `i.checked_mul(j)` will add checks[1], without needing to use undocumented vendor specific builtins, like in C/C++[2]. [0] https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html [1] https://doc.rust-lang.org/std/primitive.u32.html#method.checked_mul https://doc.rust-lang.org/std/primitive.u32.html#method.chec... [2] https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins...
- santoshalper 4y ago"Out of 7 billion people on this planet, the number that I'd personally trust to reliaby write CVE-free C code is in the low triple digits. I'm not one of them." My number is zero. I do not believe it is possible to build a truly safe C program of any meaningful complexity.
- deleted 4y ago[deleted]
- m3047 4y ago> Specifically, I do not think I'm smart enough to violate the Chrome team's Rule of 2 I simply don't write only C, or these days much C at all. What I write mostly is Python, and if I can't optimize that enough then I write C; or call C. Of course when you're calling somebody else's libs, all bets are off; and I don't think it matters what language the lib is written in. The last time I needed a serde that "went to eleven" I wrote it in Rust using PyO3. I'm not saying it was good Rust. I wouldn't know. The compiler is a bitch. It's too hard to reason about the machine. Luckily, I wasn't asking it to do much except some byte hacking in a buffer. Reasoning about the machine is becoming more problematic as exotic architectures proliferate and compilers unceasingly do increasingly weirder optimizing shit. Dunno if it matters what the language is.