Slashdot Mirror


Secure, Efficient and Easy C programming

cras writes "Feeling a bit of masochist today.. First in the morning I wrote Secure, Efficient and Easy C Programming Mini-HOWTO. And since I already spent a few hours with it, I figured I might just as well see what Slashdot people would think about it."

13 of 347 comments (clear)

  1. Is this news? by mthed · · Score: 5, Insightful

    Some guy spent a couple of hours writing a first draft of a Howto. Thanks Slashdot, I'm sure glad you didn't let this one slip through the cracks! Besides, who cares about these kludgy ways of handling memory. If you don't wan't to worry about memory allocation use C# or java or something. Otherwise, stop eating quiche and write solid code.

    --
    "There's a madness to my method." -mthed
  2. These are common tricks by pclminion · · Score: 5, Insightful
    It's a good start at a HOWTO, but needs some serious fleshing out. These are common tricks that most serious, experienced C programmers have in their bag.

    Some of my personal favorites include:

    • Exceptions in C. You can get quite natural-looking exception handling in C, with some convoluted macros. I'm sure most hardcore C coders have come up with their own implementations. Many security bugs happen in parts of the code that handle errors, precisely because errors are rare, and those parts of the code don't get tested well. Using a unified, exception-driven approach to error handling can cut down the risks. IF you do it right.
    • The alloca() function. This allocates memory directly off the stack, which is freed when the function returns. Very useful for cases where you want a stack buffer but aren't sure how big it needs to be. Like any other stack buffer, you need to take care not to overflow it. There are portability concerns with this function, but it can still be useful.
    • Variable-sized block-chained allocators, which pull chunks of memory out of preallocated segments. The segments are chained together in a linked list. Very effective when you need to make a lot of variable-sized allocations, and do it fast, dammit. It also makes freeing the allocated memory blazingly fast, although it's a "free all or none" approach.
    • "Hardened" allocators, which allocate blocks in multiples of the page size, and set memory protections in such a way that buffer overruns cause crashes. This is the easiest way to prevent ANY kind of buffer overrun vulnerability, but wastes memory. See Electric Fence.
    Look people.. It takes a keen eye and major discipline to write secure C code. It is not impossible. You have to get in the habit of subconsciously checking yourself at EVERY turn. "Am I accessing a stack variable? Am I doing it CORRECTLY?"

    DISCIPLINE, DISCPLINE, DISCIPLINE. I fully expect to see the usual barrage of comments to the tune of: "C is outdated, insecure, brittle, yadda yadda..." No. Some PROGRAMMERS are "outdated, insecure, and brittle."

    The C language doesn't write bugs. Programmers write bugs. If the programmer can't handle C, then take it away from him. But don't try to take it away from ME.

  3. Bad implementation of a heap... by lkaos · · Score: 4, Insightful

    See HeapAlloc and friends in Win32 for proper implementation.

    At any rate, there are better ways to make sure one never leaks memory problems:

    1) always set a freed pointer to 0. Most architectures have a predictable behavior in dereferencing a 0 (throws an exceptions).

    2) Limit all malloc/free pairs to the same function. If a function just has to allocate and return some buffer, give it a meaningful name to that effect and all a corresponding free version. Then, you can follow the above rule.

    3) assert()s are your friend. Use them religiously. They can always be shut off.

    4) Use memory tracking software (purify) before ship.

    Yes, it's easier to shoot yourself in the foot with C, but you'll gain a huge performance increase. It's all about using the right tool for the right job.

    --
    int func(int a);
    func((b += 3, b));
  4. As a lib and/or in general programming tutorials by Mas3 · · Score: 2, Insightful

    This looks like a good idea for a lib (or more) that covers those issues. It might be already exists, but it's not very well known. (To beginners)

    The other problem is that security issues usually aren't mentioned in general programming tutorials (and books).
    If beginners would be pointed to techniques like this (with explanations why) lots of typical mistakes would not happens.

    --
    Stefan

    Looking for Developers, new project members, testers or help? Want to provide your abilities ?
    DevCounter ( http://devcounter.berlios.de/ )
    An open, free & independent developer pool.

  5. Re:Definitely useful by Kragg · · Score: 5, Insightful

    Wow. This is one of the few genuinely insightful comments I've come across.

    Prototyping in a higher-level language (c# is easy, java everyone knows) is a superb idea, provided you
    - can release the final product as interpreted, with slow execution speed
    - can afford the time to port all to C, in which case DO, this is an excellent way to make a watertight C program
    - are happy to learn how to make managed code/vm code call to native and vice-versa (this is far from a trivial problem)

    There are apps that fit into all 3 categories, and if your end-result should be a watertight C program, it may even be faster to prototype.

    Fight the conventional wisdom! make good code by doing it right, not by being a genius who can hold 4000 variables in his mind over a month-long project (because you aren't one anyway).

    --
    If you can't see this, click here to enable sigs.
  6. aggressive use of glib by chtephan · · Score: 4, Insightful

    In my last project, I used glib from the ground up. I wrote several thousand lines of code before testing it. I made some very aggressive use of glib and gobject. After the code compiled and did not give any runtime warnings anymore it did not contain a single memory leak (verified using valgrind).

    glib containts a lot of useful things: lists, trees, hash tables, memory pools, string handling functions and a lot more, everything thread safe.

    gobject contains tools on top of glib like "classes" and "objects". It's not the same as in C++ or java, but also very useful. Runtime classes oder data types, generic object properties, reference counting, signal callback, runtime type checking, etc...

    The code ist now full of g_... and it took longer than usual because I had to read the documentation, but I think these libraries are very great, and provide a solution for nearly everything that has to do with abstract data types and dynamic memory allocation.

    And it's very lightweight, fast and efficient.

  7. Re:Mirror of HOW-TO in case it gets slashdotted by Anonymous Coward · · Score: 1, Insightful

    Some people couldn't care less about moderation. Most of us are reading at -1. So take that karma and shove it.

  8. What C can do that Perl can't by yerricde · · Score: 5, Insightful

    I still have yet to write a single useful C program that I couldn't have done in Perl.

    Can you write a video driver with acceptable performance in Perl? Can you write programs that do things other than text manipulation, such as (say) a 3D engine and make them faster in Perl than in C? Remember that in the real world, time is money because a shorter execution time means lower system requirements and thus a larger market for mass-market desktop applications.

    --
    Will I retire or break 10K?
    1. Re:What C can do that Perl can't by Anonymous Coward · · Score: 3, Insightful

      The claim was not "can", it was "have". Have you written a video driver? Have you written a 3D engine?

      Neither have I. Neither have most programmers. If you don't work for a company that makes graphics hardware or operating systems, I suspect you probably never will -- at least, not a "real world" one where performance really matters.

      For the majority of programs, there are more appropriate languages. Some programs may require C, but only a small percentage.

  9. Re:data stacks (NSAutoReleasePool vs. NSZone) by Jimithing+DMB · · Score: 5, Insightful

    Well, not quite. An NSAutoReleasePool does not allocate a large region of memory and suballocate objects out of that. What an NSAutoReleasePool does is make it possible to avoid explicitly sending the release message for temporary objects.

    For example, from Foo() I allocate an NSObject with [[NSObject alloc] init] and pass that as an argument to Bar() which takes ownership of it. However, I must then ensure that I release the object because Bar() is following good coding practices and retains it, so thus with alloc+retain it's reference count is now 2. So instead what I do is Bar([[[NSObject alloc] init] autorelease]) which allocates NSOjbect (with ref count one) initializes it, marks it for autorelease, and passes sends it to Bar() which retains it (ref count 2) and keeps a pointer to it (presumably it is a method of a class). Coming out of bar the ref count is now 2, and perhaps Foo() proceeds to do some other things. Presumably at some point higher up the call stack (or perhaps at the beginning of Foo()) an NSAutoReleasePool was allocated. At the corresponding exit point (either at the end of Foo() or the end of whatever higher up function) [whateverpool release] will be called. When the pool is released, it will call release on any objects it has been asked to take ownership of. At this point one of two things it true. Either the class that Bar() belongs to has already released the object and thus its reference count went back down to one, and now is going to zero (so bye-bye), or the class that Bar() belongs to has not released the object and doing this release merely brings the refcount back to one such that when the other owner releases the object, its refconut will be zero and it will be freed.

    Sorry if that was confusing, but in reality it's really not. It also really helps out when you are coding functions that allocate ObjectA, then allocate ObjectB, then ObjectC, and then find out something is wrong and need to "roll back" to the begining. If you allocate an NSAutoReleasePool at the beginning, and autorelease everything you alloc then if you error out you can free the release pool and everything gets released. If you don't you can simply retain what you need and then free the autorelease pool.

    Anyway.. what this guy is REALLY talking about is NSZone. NSZone allocates a chunk of memory which other objects will be allocated from. The caveat being that while the memory will be freed, the objects will not be properly destroyed. Now this guy was talking about holding C strings and the like, so this is not a problem. However, had he been holding some C++ or objective-C objects this would be a problem as none of the destructors/deallocators would ever be called.

    I think what it all boils down to is that programmers need to read more code than they write and that we should really be getting Masters of Fine Arts in Programming. I completely agreed with what Dr. Gabriel said. Programming is about as much like building a bridge as writing poetry is. That is to say.. not much.

    Going along with that thought, I think it should be pointed out that /EVERYONE/ here who programs in any language (but specifically C programmers, and ESPECIALLY C++ coders) needs to learn Cocoa and Objective-C. I imagine some of the C++ whiny bitches are going to continue to whine about how much easier and better C++ is, but for those of us who actually prefer to wrangle pointers, Objective-C is where it's at. It's like C with JUST enough object orientation, but not overdone in some committee like C++. Also, one should note that I do like C++ quite a bit, but sometimes there's too many provided ways to do things. With Objective-C, the provided ways are almost all good. In addition, like C or C++ you are not limited to doing it that way, it's just that Objective-C only makes it easy to do good things.

    Think for example of wxWindows vs. Microsoft MFC. wxWindows is suprisingly similar to Cocoa (although wxWindows does not do ref counting so making sure that one and only one class ever owns an object can be problematic at times). MFC, on the other hand, is rather a bear to work with as Microsoft has written it such that an MFC programmer /can/ do things multiple ways, none of which work very well. Obviously this is a generalization, but I think the average MFC programmer will understand where I'm coming from here. That is, again, except for the whiny C++ and MFC bitches who can't figure pointers out. Go home!

  10. Re:Nice little remark, there, michael by cubal · · Score: 2, Insightful

    no, no, no, that's a paradox... an oxymoron is two words or ideas juxtaposed that _imply_ contradiction, or that wouldn't normally fit together ("...pretty ugly","Microsoft Works","Military Intelligence")

    "Secure, efficient and easy" would at first seem to be impossible, but on closer inspection is not so... that makes it a paradox.

    (admittedly, it has oxymoron-like properties, but I think the fact that there are three parts to it rather than two negates that)

  11. Re:K&R designed for paper, not for monitors by Anonymous Coward · · Score: 1, Insightful

    Books use K&R style to limit the size of code because it costs more money to print more pages. It has nothing to do with being able to see more code.

    I can fit over 120 lines on my screen. If your routine is bigger than that, then in 99% of the cases you had better rethink your code. In the other 1%, chances are that you're in some big switch statement or cascading if/else. Each of those better be able to fit on a screen.

    Bottom line: if understanding your code requires being able to see a lot of it at a time, then your design is shite.

  12. Is it just me or does slashdot suck more and more? by sgml4kids · · Score: 2, Insightful


    1. There are more ways to exploit C code than looking for buffer overflows. race conditions are a more prevalent and portably exploitable vulnerability of a large body of C code (eg. config file integrity). Following the author's guidelines barely improves the security of any program. If you want to make your code secure, spend a month reading the 1000s of articles online (or at the ACM or IEEE or CERT/CC) about how software is compromised. This is so much crap.

    2. This is so not news for so many reasons. Slashdot is becoming so out of touch (yes, isn't it cool knowing some freak shoved a Pentium giga-twat up his ass and replaced his eyeballs with WiFi LCD projectors?) I sometimes get nauseated reading these stupid "news" items.

    Slashdot: News for the Herd. Stuff that goes "Baaaaaa"