3 ms·
I don't disagree, and thank you for the pointers. What I was talking about is API design, and I don't think you are contradicting with what I was saying. As to
by jstimpfle 8y ago
I don't disagree, and thank you for the pointers. What I was talking about is API design, and I don't think you are contradicting with what I was saying.
As to C being more bug prone, for my own code I believe the biggest improvement to correctness would come from fat pointers with array size information, enabling bounds checking. That would help to spot errors in little-used code. On the other hand, fat pointers and other sophisticated methods can get in the way of a clean normalized data organization. A lot more flexibility with respect to data and code organization is possible in plain C, which is a great enabler of software in the first place. In the end, if the code is simpler and shorter and has more deterministic performance, but each line of code is more bug prone, that can still be a worthwhile tradeoff.
By the way, I don't view myself as a very careful C programmer and I don't have the patience to check my code against all kinds of UB and such. I've never done fuzzing (I might try it). But for example valgrind has revealed only few problems once my code was working, in the past. The main problem in my eyes is when coding C in an object-oriented style with endless pointers and lifetime issues. What I do is I try to avoid tree structures (including XML) since I feel it's a lot of peeking and poking and traversing with little reward. Instead, I typically use global data, flat arrays, and integer indices, and as a result the code usually becomes very straightforward.
By the way, for a project the size of an XML parser I wouldn't feel shame for such a tiny list of CVEs :-).
- ekidd 8y ago> for my own code I think the biggest improvement to correctness would come from fat pointers with array size information, enabling bounds checking. Yes. In fact, I suspect that's the single biggest thing most C programmers could do to avoid CVEs. Rust does something similar with bounds-checked "slice types" like &[T], and it makes a huge difference. For example, I wrote a VobSub subtitle decoder in Rust and I fuzzed it with 'cargo fuzz' and AFL. VobSub is a hairy binary format, and it's easy to make mistakes. AFL found 5 bugs: - 3 were incorrect uses of Rust's &[T] type, all of which were detected by the bounds checks. - 2 were integer overflows, both caught by the fact that Rust panics on overflow in debug builds. Neither of these looked exploitable—one was harmless, and the other one would have been caught the first time it tried to index a &[T]. So Rust's borrow checker is useful. But the single biggest win turned out to be having bounds-checked array slices, as you suggested. > By the way, for a project the size of an XML parser I wouldn't feel shame for such a tiny list of CVEs :-). I didn't write the XML parser. That was written by James Clark, who was something of a legend in the SGML and early XML world. So even if you pick your C dependencies carefully, it's still risky. (And my code has been fuzzed much less than Expat.) But to paraphrase various recent medical claims, there is "no safe level" of CVEs. > I've never done fuzzing (I might try it). I recommend it to anybody who works with pointers or who parses untrusted data. It's fun to watch AFL generate a billion(!) test cases and slowly ferret out "impossible" conditions. But it may also make you completely paranoid about bugs.
- kbenson 8y ago> But it may also make you completely paranoid about bugs. As you should be. It's not paranoia if they really are out to get you. The the bugs are, they really are...