Slashdot Mirror


How Do You Know Your Code is Secure?

bvc writes "Marucs Ranum notes that 'It's really hard to tell the difference between a program that works and one that just appears to work.' He explains that he just recently found a buffer overflow in Firewall Toolkit (FWTK), code that he wrote back in 1994. How do you go about making sure your code is secure? Especially if you have to write in a language like C or C++?"

86 of 349 comments (clear)

  1. You don't by CockMonster · · Score: 5, Funny

    Just get others to formally review it so if anything is found, there's collective responsibilty

    1. Re:You don't by Anonymous Coward · · Score: 2, Funny
      Prophylactic: A preventive measure. The word comes from the Greek for "an advance guard," an apt term for a measure taken to fend off a disease or another unwanted consequence.


      Sorry CockMonster, with today's DNA testing, getting others to participate in your virgin sacrifice wouldn't save you if you had a buffer overflow.

      *Warning* as appropriate as prophylactic might seem under its definition for use in the computer industry when talking about firewalls, sandboxes, etc, please keep in mind that some female is probably going to holler sexual harassment when they hear it. Just as they would if you mentioned their stack overflow.
    2. Re:You don't by jorgevillalobos · · Score: 4, Insightful

      Modded as funny? This is as real as it gets. At least in the private sector.

    3. Re:You don't by hackstraw · · Score: 2, Insightful

      Just get others to formally review it so if anything is found, there's collective responsibilty

      Yes, that is funny, but there is truth to it as well (which is why its funny).

      Security, software development, and everything else is a process, not an event. It gets better over time, and basically, the way that issues come out is for them to be found "in the wild". And as these issues are found, better tools and techniques make the process better over time, but I don't envision a world where people just think of bugfree, usable, featureful software that just appears, but all in all it keeps getting better.

      The error in question:while(lp != (struct listelem *)0) {
                      free(lp);
                      lp = lp->next;
              }
      is pretty silly, and I don't know how it took over a decade to find that. In my experience, code like that crashes pretty regularly, and debugging it will point to the error.

      Today, what some programmers do is to do FREE(lp); where FREE() is a macro or something that does if (a) { free(a); a=NULL; }. This prevents double frees, and ensures that future use of the pointer will predictably die with a null pointer exception. In 2006, bugs like this should not find themselves in C code. We now check our stuff, use languates or tools that check for crap like this for us, or whatever. In 1994, I guess it was OK for such a bug to be interoduced into code, but not in 2006.

    4. Re:You don't by Anonymous Coward · · Score: 2, Informative

      The purpose of his macro isn't to fix the dangling reference problem. The purpose is to help developers find dangling reference problems in their code.

  2. Verified by Anonymous Coward · · Score: 5, Funny

    I get mine verified by microsoft

    1. Re:Verified by Anonymous Coward · · Score: 2, Informative

      On one hand your comment is funny due to the chronic security risks associated with MS products.

      On the other hand, MS has some of the best code analysis technology available in Prefast, FXCop, SAL, and Application Verifier:

      http://msdn.microsoft.com/msdnmag/issues/05/11/SDL /default.aspx

      Disclaimer from the linked content:

      "Security tools will not make your software secure. They will help, but tools alone do not make code resilient to attack. There is simply no replacement for having a knowledgeable work force that will use the tools to enforce policy."

  3. Secure? by nahime · · Score: 2, Insightful

    Secure?? What does it mean?

  4. Shovel method by dangitman · · Score: 4, Funny

    I hit it with a shovel. If the code doesn't fall apart, I know it's pretty securely attached to my computer. If not, I add more epoxy glue.

    --
    ... and then they built the supercollider.
  5. Don't use C++ as if it was only "C with classes" by quigonn · · Score: 4, Insightful

    Modern C++ provides a very nice and functional Standard Library which provides a lot of functionality and data structures such as strings, vectors, lists, maps, sets. While using these available classes does not completely rule out making programming mistakes related to buffer overflows and such, it at least minimizes the risk of producing stupid buffer overflow through badly done string handling. At least that's what my experience is.

    Actually, the best thing would be not to use C or C++ at all, but that's where reality comes into play. Most developers don't even have the choice which language they should use, but that is predetermined by the employer and/or supervisor.

    --
    A monkey is doing the real work for me.
  6. Avoid direct memory access by Ed+Avis · · Score: 4, Insightful

    You introduce buffer overflows when you deal with buffers directly. In conventional C with its standard library you're encouraged to do this rather a lot, for example many of the string functions expect you to allocate a char buffer of big enough size and pass it in. The language's arrays are just syntactic sugar for accessing raw memory, with no bounds checks.

    However you don't have to do it like this, especially not in C++ which has a safe string class (for example) as part of its standard library. Unfortunately C++'s vector type still doesn't do bounds checking with the usual [] dereferencing - you have to call the at() method if you want to be safe. But the general principle is: don't do memory management yourself, use some higher-level library (which exist for C too) and let someone else do the memory management for you.

    You can write a C++ program and be pretty confident it doesn't have buffer overruns simply because it doesn't use pointers or fixed-size buffers, but relies on the resizable standard library containers.

    --
    -- Ed Avis ed@membled.com
    1. Re:Avoid direct memory access by ojQj · · Score: 5, Informative

      Unfortunately stl isn't binary compatible. That means you have to make sure you've compiled with exactly the same version of the stl with all the components of your program which accept and pass strings. This in turn makes it impossible to release different parts of your program separately from each other if you are using the stl at the interface between your components.

      There are a couple of solutions to this problem:

      1.) Pass character arrays at the interfaces between your components and immediately put those character arrays under the control of your library once they come in.
      2.) Write or find your own string library and pass that string class between program components. Be careful when doing this. Mistakes will come back to byte you.

      All of it's kind of nasty. It'd be nice if C++ could standardize their binary representation, even if it's only a standard valid per platform.

      Then there's also:

      3.) Choose a language which unlike C++ already has a standardized binary representation for strings, or a system global interpreter for a varying binary representation. This is just an extension of the "higher-level library which does the memory management for you" option really.

      Don't get me wrong -- I'm agreeing with the parent post. I'm just adding a caveat.

    2. Re:Avoid direct memory access by Viol8 · · Score: 4, Insightful

      "simply because it doesn't use pointers "

      Err, how much C++ have you written? I've yet to see any complex C++ *without* pointers since you cant reference or use dynamically created objects using the new operator without them. Not to mention in 101 other instances where they're useful.

    3. Re:Avoid direct memory access by rucs_hack · · Score: 5, Insightful

      I code predominasntly in C, and I find very few problems with allocating my own string buffers and so on. Doing your own memory allocation/deallocation does not instantly mean you have a program full of buffer overflows and security holes, although many people seem to assume this is the case.

      What does that is rushed code, poor design and inadequate testing. These feature heavily in the vast majority of commercially produced code I've seen. Frankly most of what I've seen is horrifically bad. With code of such low quality, C should be avoided, but that's not C's fault, it's crap house coding rules. C is elegent, minimal, and mindbendingly fast. This does not mark it as ideal for enterprise tools, but it does have a place there, for time intensive operations.

      It is extremely easy to ensure buffers in C have a strictly limited inputs, and do not encounter overflows. It's also easy to not do this, and thus faster. That I suspect, is where most of the problems come from.

      Open source code used in the enterprise seems nowadays to be starting to suffer from similer problems to the commercial code I've seen, although commenting schemes are better. The problem seems to me to be a feeling that things must be pushed forward to compete. That isn't a good plan. Slower development, more testing before actual deployment, and less feature creep are what is needed.

    4. Re:Avoid direct memory access by AuMatar · · Score: 2, Insightful

      I prefer to just fire the bad coders. Really, memory management is pretty fucking simple. You request a resource, you use it, you release it. CS is full of this sequence.

      *Using a file
      *Using a semaphore
      *Using a database connection
      *Any other resource that is unique

      If you can't get this simple concept, you shouldn't be programming. Ever.

      The only difficulty is if you have ownership of pointers bouning all over. Of course, I've never seen a good design that did that. Good modular design solves the ownership problem for you in 99.9% of cases. In fact, if I ever find a place in code where it isn't clear, its a warning to me that I need to redesign that part of the codebase.

      --
      I still have more fans than freaks. WTF is wrong with you people?
  7. Easy by $pearhead · · Score: 5, Funny
    Just make sure your buffers are really really REALLY big:

    char nooverflowbuffer[234523400];

    sprintf("Enter something:");
    scanf("%s", nooverflowbuffer);
    ... or maybe not ...
    1. Re:Easy by swilver · · Score: 2, Informative
      Buffer overflows may not be the only security problem, but at the moment they are by far the most common security problem. A race condition MIGHT allow you some unauthorized access to certain things.. more likely however, it will just show up as a minor malfunction in the program without any security implications at all.

      It certainly won't allow you to execute arbitrary code in for example a Java application -- infact, you'd have to find a bug in the JVM itself or one of the native implementations of basic classes like String to have any chance of that. That is however highly unlikely given the amount of use these core parts of Java see.

    2. Re:Easy by gnasher719 · · Score: 3, Funny

      The second version seems more secure, because it doesn't compile.
      The first version seems to be quite secure as well, because it is likely to crash immediately, and obvious crashes will usually get fixed quickly.

      Hint: What is the format string in >> sprintf("Enter something: "); and where will the output go?

    3. Re:Easy by h2g2bob · · Score: 2, Informative

      I'd suggest:

      #define BUFSZ 1024
      char buf[BUFSZ];

      printf("Enter something: ");
      fgets(buf, BUFSZ, stdin); /* the SECURE way to do it, don't even think of using gets() or scanf()! */
      strip_newline(buf, BUFSZ); /* some function to remove trailing newline */

  8. Security by El+Lobo · · Score: 2, Insightful
    It is hard to be sure that your code have no bugs or security holes. That's because even the Hello world program is using implicity a lot of libraries/dependences that are not written by you and are sometimes very complex. For example, writting Hello World to the console invokes a string handling unit in any hight level languge. String handling units are per se complex unit and there may be a lot of bugs there that may affect your code's security if those bugs are exploited.

    Writting in C/C++ doesn't do the whole thing better. A strong/typed language like Delphi or a managed language like C# are less likely to have any buffer overflow type bugs, etc, but you never know. Code writting is not pizza baking.

    --
    It's time to realise that Abble's products are the biggest abomination these days. Just say NO to the dumb iAbble way!!
  9. Same way you hunt bugs by Llywelyn · · Score: 5, Informative

    0) Don't "roll your own" security unless absolutely necessary. Find someone else's implementations and work with those.

    1) Design the code for security, code to that design. I've seen of security bugs creep into code because it was never designed to be secure.

    2) Use static code checkers--such as Splint for C/C++ and FindBugs for Java--that look for security vulnerabilities.

    3) Peer reviews/code audits. Sit down with your code (and have others who know how to look for security vulnerabilities sit down with your code) and do a full review.

    Nothing is foolproof, but every little bit helps. It should be noted that all of the above also improve the overall quality of the code and reduce the number of overall bugs: Finding existent implementations of features that can be used can reduce maintenance and reduce bugs; Designing the code and putting it through a proper design review can catch a lot of logic problems and ensure that the code fits the requirements list--I've seen a huge number of synchronization bugs in Java simply because the author didn't know how to use synchronization properly; static code checkers find a lot more than just security bugs; and Peer Reviews/Code Audits can help isolate a variety of problems.

    --
    Integrate Keynote and LaTeX
    1. Re:Same way you hunt bugs by autocracy · · Score: 2, Funny
      Yes, please continue to implement your own security.

      Especially focus on validating usernames and passwords against an SQL database. That's my favorite.

      --
      SIG: HUP
  10. The answer is simple - you never know by tuxlove · · Score: 4, Insightful

    Anyone who develops software knows the axiom - the number of bugs discovered in any piece of software is directly proportional to the amount of testing you perform on that software. From this, it follows that you can keep testing forever and at best only asymptotically approach bug-free code. Sounds hyperbolic, but I've observed it to be true in my experience. And as long as there are bugs, there are bound to be security bugs.

    You can only minimize the risk that security issues will be found with any software. The best way to do this is to perform a rigorous code audit, preferably by security professionals. And if you can, make the software open source. You get a lot more eyes staring at it for free that way.

    1. Re:The answer is simple - you never know by Rogerborg · · Score: 2, Informative

      Another issue with (manual) testing is that testers tend to pursue bugs aggressively in whatever area they first happen to find some, which means you get good depth coverage, but can end up missing out on testing whole areas of functionality.

      --
      If you were blocking sigs, you wouldn't have to read this.
    2. Re:The answer is simple - you never know by TheRaven64 · · Score: 4, Interesting
      Don't trust your own code. The reason OpenBSD is secure is party because the code is security audited constantly, but also partly because much of the system is written on the assumption that the rest of it is buggy. Isolate your code as much as possible. If you can get away with it, fork off separate modules and communicate between them over a well-defined interface. Validate everything that is received. Don't let any of your code run with more privileges than it needs; make good use of chroot and setuid. If you don't need to be able to access anything on the filesystem then the first thing you should do is make an empty directory and chroot there; that way an attacker who compromises your code can't do anything useful.

      The best advice I read was from the Erlang documentation. It suggested that you program defensively on a system level, but not on a module level. If a module receives input it can't understand, or thinks it is in an invalid state, the correct behaviour is for it to crash. A system of monitors should deal with failures of components, because they can determine how the failure will affect other components. There has only been one remote root hole in OpenBSD in the last ten years, and it would have been avoided if the OpenSSH developers had used this principle.

      --
      I am TheRaven on Soylent News
  11. What's the matter with C/C++? by mangu · · Score: 4, Insightful
    Why do people keep this meme that C/C++ is so insecure? Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.


    It's not that C/C++ is so insecure by itself, the problem is that programmers may not have used the best programming practices. There are plenty of libraries for handling strings and memory allocation in C, in C++ there are string and storage classes that do as much or as little checking as you need.


    When you are an expert programmer there are places where you need more efficiency than the super-safe string routines can give you. It's the job of the expert to determine exactly how to balance efficiency against security, and only C/C++ can give you this balance.

    1. Re:What's the matter with C/C++? by Anonymous Coward · · Score: 5, Funny

      'It's not that C/C++ is so insecure by itself'

      yeah a gun by itself is not insecure either....
      try giving it to a baby.....
      well I prefer a baby with a knife...I can still run faster than him...

    2. Re:What's the matter with C/C++? by Viol8 · · Score: 4, Insightful

      C/C++ are very powerful languages because they let you do pretty much what you like. But with this freedom comes the ability to shoot yourself in the foot badly either due to design errors, sloppy programming or just genuine mistakes. Personally I don't mind this risk but other people (usually the types who knock C/C++) can't really function in an enviroment that doesn't hold their hand and protect them from their own mistakes. Horses for courses.

    3. Re:What's the matter with C/C++? by TheRaven64 · · Score: 2, Interesting

      Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++. Not in the case of Smalltalk. The Squeak VM is written in a subset of Smalltalk which is compiled by a compiler written in Smalltalk into native code. Most of the Java VM and compiler, I believe are written in the same way.

      There are plenty of libraries for handling strings and memory allocation in C, in C++ there are string and storage classes that do as much or as little checking as you need. Once you have added enough to a language that it no longer looks like the original, then it's time to ask yourself if you picked the correct language for the job to start with. I could write a dynamic dispatch mechanism with inheritance for use in C, but I would start to wonder if I shouldn't really have written the entire project in Objective-C instead.
      --
      I am TheRaven on Soylent News
    4. Re:What's the matter with C/C++? by CDarklock · · Score: 2, Interesting

      > Why do people keep this meme that C/C++ is so insecure?

      Because bugs don't belong to programmers, they belong to code.

      Imagine the difference between "I fixed a Linux kernel bug", which earns you much respect from the community, and "I fixed one of Linus Torvalds' bugs" - which is a rather offensive thing to say.

      So while the insecurity is the programmer, not the language, we can't blame the programmer. It's simply not acceptable.

      --
      Microsoft cheerleader, blue flag waving, you got a problem with that?
    5. Re:What's the matter with C/C++? by arevos · · Score: 4, Insightful

      Why do people keep this meme that C/C++ is so insecure? Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.

      C and C++ have a larger domain that can suffer from buffer overflows than languages with automatic memory management. In C, a buffer overflow can potentially occur at any point in your source code. In a language which automatically manages memory and checks bounds, the possible points at which buffer overflows can occur are reduced. This does not necessarily make the application more secure, but it does mean that there are less points at which it can be compromised.

      When you are an expert programmer there are places where you need more efficiency than the super-safe string routines can give you. It's the job of the expert to determine exactly how to balance efficiency against security, and only C/C++ can give you this balance.

      I'm not sure that the efficiency increase from dropping boundary checks is often necessary, except possibly in high-end 3D games. Also, many languages allow for binary libraries written in C, so it would be possible to write an application in C#, Python, Ruby or whatever, and farm out any efficiency-critical routines to a library.

    6. Re:What's the matter with C/C++? by Decaff · · Score: 2, Informative

      Why do people keep this meme that C/C++ is so insecure? Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.

      Which is irrelevant. That code can be thoroughly tested and safe, even with the fundamental issues of C++. What matters is your code. You probably won't get the chance to test that code thousands or millions of times the way the compiler/library or interpreter has been.

      It's not that C/C++ is so insecure by itself, the problem is that programmers may not have used the best programming practices. There are plenty of libraries for handling strings and memory allocation in C, in C++ there are string and storage classes that do as much or as little checking as you need.

      C/C++ IS insecure by itself, because of what it allows you to do. No programmer is perfect, and we all make mistakes. Driving without a safety belt is fundamentally less safe, and you can't argue it away by talking about 'people not driving skillfully enough'.

      When you are an expert programmer there are places where you need more efficiency than the super-safe string routines can give you. It's the job of the expert to determine exactly how to balance efficiency against security, and only C/C++ can give you this balance.

      I would be very surprised to know exactly when you think this is the case. If it is, it is for the most specialised circumstances. The problem with C/C++ is you have this division between safe (with checks) or fast. Other languages get around this problem, by including safety, but allowing the safety checks to be optimised away by code analysis, often at run time. For example, you could have code something like this:

      int [] array = new int [4];
      for (int i = 0; i 4; i++) array[i] = i;

      The compiler/runtime can analyse this code, and because it is obvious that the bounds of 'array' are never exceeded here, remove any checking and optimise hugely.

      It is a myth that you need to balance efficiency against security the C/C++ way.

    7. Re:What's the matter with C/C++? by Tyler+Durden · · Score: 2, Insightful

      And that's the problem these days. Too many babies using C/C++.

      --
      Happy people make bad consumers.
    8. Re:What's the matter with C/C++? by canuck57 · · Score: 2, Insightful

      yeah a gun by itself is not insecure either.... try giving it to a baby.....

      There is the crux of the C/C++ problem, we give an oozie to to 3 year olds without the training and knowledge. 9/10 C/C++ programmers I ever interviewed failed to properly explain how pointers work. Those that did answer pointer questions correctly tend to have programmed more securely than those that put */&/** by memory.

      It also comes down to money, a good C/C++ programmer isn't cheap.

    9. Re:What's the matter with C/C++? by grammar+fascist · · Score: 2, Insightful
      Personally I don't mind this risk but other people (usually the types who knock C/C++) can't really function in an enviroment that doesn't hold their hand and protect them from their own mistakes.

      There are plenty of us who are perfectly capable of functioning in that environment but choose not to, preferring to focus mental energy on algorithms rather than silly implementation details like whether that pointer I've got points to something stack-allocated or heap-allocated. Besides that, I do mind the risk, because I have the mental capacity and maturity to understand that, even though most of the code I write that compiles is also correct, I'm not perfect.
      --
      I got my Linux laptop at System76.
  12. Grammar by noz · · Score: 2, Insightful
    Marucs Ranum notes taht [...]
    Marucs' code is more secure than Zonk's editing.
  13. Some possibilities by AArmadillo · · Score: 2, Insightful

    You cannot know for sure (unless you want to develop code by mathematical proof, which requires a considerable amount of effort). However, you can do some things to help prevent buffer overflows and security problems in general: - encapsulate all buffer access, and make the interface overflow-safe. Then you need only ensure your encapulation is secure. - use a static code analysis tool that detects buffer overflows. I do not know of any open source ones off the top of my head, but I remember seeing an article on slashdot a few months ago about a new open source static analysis tool - avoid unsafe functions. Nearly all standard C functions that deal with buffers are unsafe (that is, a typo or oversight can give you a difficult to detect buffer overflow). Sprintf and strcpy are common culprits off the top of my head. If you're writing for Windows, the Microsoft extensions to the standard library have equivalent 'secure' functions (usually postfixed with _s). I do not know if there is an open source equivalent. - Use your compiler's buffer overrun detection. I think this is -fmudflap for gcc. That's all I can think of for now.

    1. Re:Some possibilities by zCyl · · Score: 5, Funny
      You cannot know for sure (unless you want to develop code by mathematical proof

      In the words of the great Donald Knuth, "Beware of bugs in the above code; I have only proved it correct, not tried it."
  14. Valgrind by chatgris · · Score: 5, Informative

    By using valgrind. It's a virtual machine of sorts that runs your code and checks for any memory problems at all, including use of uninitialized memory. Combine that with thorough test cases, and you can be virtually assured that you have no memory errors in your C/C++ code.

    However, security is a lot more than buffer overflows... but at least it brings you up to the relative security of Java, with speed to boot.

    --
    Open Your Mind. Open Your Source.
  15. Assume failure by zCyl · · Score: 5, Insightful

    Every function should be designed with the assumption that its input is faulty, and should have safe failure modes for every possible value and all possible content. Any unsafe external libraries must be wrapped in handlers which verify the data being passed to them with a similar mindset. Do not EVER presume data will be of a certain form, or that a function will be used a certain way. If sequential routines are becoming long such that you cannot verify the accurate function or the absence of a buffer overflow immediately in your head, then stop and look for a way to break it down into smaller abstract pieces.

    Combine this mentality with the usage of safe classes as datatypes whenever possible, so that you can wrap your input verification into the functionality of the classes. If prudent, wrap external library routines in classes which manage the interaction with them, and which verify the data content being passed.

    Use test suites to test every component of your program, and be sure to include invalid and pathologically insane input in your test suites.

    Do not trade security for efficiency. And don't forget to cross your fingers.

    1. Re:Assume failure by TheRaven64 · · Score: 4, Funny

      Fuck off, private functions below the public API should never have to check their input. I completely agree. There are no bugs in my code, just in the code of people calling my code.
      --
      I am TheRaven on Soylent News
  16. Re:Don't use C++ as if it was only "C with classes by Viol8 · · Score: 2, Insightful

    The mostly STL gets rid of the old problems such as buffer overflows but introduces new ones that can a lot more subtle and harder to track down such as deep/shallow copy issues. Personally (and I'm probably in the minority) I prefer to deal with the old fashioned bugs since you can usually guess where they're happening whereas in a highly abstracted C++ program using the STL with lots of objects being copied and references flying around it can be a LOT harder to figure out whats really going on , especially since different compilers do different things under the hood.

  17. Re:I don't. by Anonymous Coward · · Score: 5, Informative

    Grammar tip: "Effect" is a verb. "Affect" is a noun.

    Um, how's that?

    Your poor grammar has a chilling effect on me. If I were you, I'd find a way to effect an improvement in your knowledge. Luckily it affects me only a little. But the fact that so few seem to understand that these two words are both verb and noun leaves me of sad affect.

  18. Don't let them use it where it matters by Anonymous Coward · · Score: 5, Funny

    I let my code have evident, gaping security flaws and make them well known. This way people will never use it in situations where security matters.

    regards,
    The author of sendmail

  19. String overflows by Rik+Sweeney · · Score: 2, Informative

    I think for some people, moving from using a language like Java to using C can cause them a multitude of problems since there's no bounds checking by default and overruns aren't caught.

    For example, I recently fixed a bug Blob And Conquer to do with Strings, the code was something like this:

    char nm[2];

    nm[0] = mission[11];
    nm[1] = mission[12];

    The code then went on to doing a

    missionNum = atoi(nm);

    Most of the time, this'd work OK because of the way atoi works. Other times though it'd stray off into other memory and pick up a random number and return a three or more digit number instead.

    Obviously there's an easy way to fix it.

  20. Re:Don't use C++ as if it was only "C with classes by Diablo1399 · · Score: 3, Insightful

    You would sacrifice the flexibility and usefulness of the STL to get a class of bugs that are old and well-known? Hardly seems like a fair trade-off to me.

  21. Proving the Unprovable by Sub+Zero+992 · · Score: 2, Insightful

    How do you validate code for correctness? Well, either you use some cool formal specification language, such as Z, and then spend a great deal of time and effort validating (which is actually very advisable for critical code in, say, device controls for medical equipment) or you use blind luck and "proven" techniques, collectively known as Good Programming Practice.

    Traditionally it has been important to "specify and validate" requirements acribically, in the belief that this is was the way to write good code. This is partly true, but that way can quickly turn your process into a dinosaur - stifling change and preventing improvement because of non-compliance with "The Requirements".

    You can try "defensive coding", which really treats all messages with great suspicion, messages being an old term for parameters. This is a cool technique, but can lead to slower code than necessary, and can lead to some bug being buried if code attempts to heuristically correct for "bad" messages (there is rarely any way to formally specify what is "bad"). You can use LINT tools (and there are very many, very sophistacted tools) which will catch a whole lot of stuff before it leaves the developer's screen. You can try practices such as pair programming and independent code inspection. On the coding side, you can even try (gasp) such methods as test driven development and contract based development.

    On the testing side, there is nothing quite like having an experienced, qualified, motivated and _empowered_ testing team. A testing team which knows how to find bugs, knows how to communicate with coders and has the power to step defects going in to production. A technique I particularly like is defect insertion - secretly insert 10 bugs into the code base and see how many get squashed, this will give you an estmate of how many defects your process doesn't find. There are other cool techniques too, some based on mathematical analysis of the code's attribute - the more complex the code the costlier it is to maintain.

    Opening up the codebase to many people might well increase the chance that someone will find the line which causes an error - but IMHO no one goes around looking for bugs unless they are looking for weaknesses. And there we have another (unethical) method - pay some hacker doodz to 'sploit your code. Hopefully they will not find a higher bidder LOL.

    All of these methods are likely to increase development effort and cost, decrease the number of defects, increase user satisfaction, decrease maintainance costs and increase well-being and harmony. So it is a trade off, perfect code is incredibly difficult to create - the question is what level of perfection are you (and your customers) willing to pay for. Problems mostly arise when expectation does not meet reality - some flakiness in an F/oss application suite is more acceptable to me than random crashes in software which cost me hundreds - or tens of thousands - or millions - of dollars.

    In order to increase some quality aspect of code (security, performance, robustness, correctness...) one can therefore focus on one or several categories - the people, the process, the culture, the tools, the technique, the time&cost etc. The choice of what to focus on is dictated by reality: no one has unlimited resources (except, almost, Google).

    There is no silver bullet - but there are golden rules. Finding people who know the difference is crucial I believe.

    (Full disclosure: Yeah, I'm looking for heavy duty PM work :)

    --
    They who would give up an essential liberty for temporary security, deserve neither liberty or security - Ben Franklin
  22. Re:Just Say No by hAckz0r · · Score: 2, Insightful
    Ada comes to mind.

    Ok, What language is your Ada compiler written in? There are very few self-hosted languages that do not rely on "C" at some level. Also, the OS and the system libraries were written in C. At some level you need to deal with the stated problem. All that being said many people are probably better off with Ada unless they actually "study" software security on a daily basis.

  23. Does language matter? by forgoil · · Score: 2, Interesting

    In this case it doesn't in one important way. Programming is the same regardless of language, since humans are the same regardless of language. What you need to write good software (again, why just secure? Why focus on a certain aspect, why not just generalize?) is skills/knowledge and good habits. My best advice here is to make sure you give yourself good coding habits. Don't say things like "I'll clean that up later" or "I will add error checks later" or something equally damaging. Give yourself good, sensible, habits and follow them. Any average programmer must know what buffer overflow means, and how to correct it. You can't even be an average programmer unless you know. So why is such insecure code written in C/C++ then? My thinking is plain mistakes and bad habits.

  24. Re:Don't use C++ as if it was only "C with classes by Viol8 · · Score: 2, Insightful

    Not necessarily , all I'm saying is that the STL can introduce bugs of its own that can be a lot harder to find than old style buffer overruns so its not a solution that will get rid of obscure coding (as opposed to logic) bugs.

  25. The only sure way I know of: Lambda calculus by Berkana · · Score: 4, Interesting

    If you program using strictly functional programming, you can not only verify that your code is 100% secure, but you can even automate the process. (Preferably in a functional programming language such as Scheme, caml, Haskel, LISP, or Erlang; imperative languages make it very difficult/slow to do with functions what functional languages do very naturally and easily.) Purely functional code can be subjected to automated code auditing easily, whereas code auditing imperative code cannot be guaranteed to catch every bug and unintentionally available abuse.

    Here's why, and why just about any computational problem can be solved using FP (functional programming):
    Functional languages conform to lambda calculus, which has been shown to be Turing equivalent, which means that any program that can be computed on a Turing machine can be solved using Lambda calculus. So long as you program using strictly functions, your program can be verified according to the rules of lambda calculus, and the verification would be as sure as a mathematical proof. This is the only sure way I know of really knowing with mathematical certainty that your application is secure.

    Pure functional programming has no assignment statements; there are no state changes for you to keep track of in your program, and in many cases abuses resulting unintended changes of state are the root of security problems. This is not to say that there is no state in functional programming; the state is maintained through function call parameters. (For example, in an imperative programming language, iteration loops keep track of a state variable that guides the running of the loop, whereas a functional program never actually keeps track of state with a variable that changes value; a functional program would carry out iteration by recursion, and the state is simply kept as a parameter passed to each call of the function. No variable with changing state is ever coded.)

    Since functional programs lack assignment statements, and assignment statements make up a large fraction of the code in imperative programs, functional programs tend to be a lot shorter for the same problem solved. (I can't give you a hard ratio, but depending on the problem, your code can be up to 90% shorter when described functionally.) Shorter code is easier to debug, which helps in securing code. The reason functional code is so much shorter is that functional programing describes the problem in terms of functions and composition of functions, whereas imperative code describes a step by step solution to the problem. Descriptions of problems in terms of functions tend to be far shorter than algorithmic descriptions of solving them, which is required in imperative code.

    Here's the biggest benefit of managing complexity with functional programming: as a coder, you NEVER have to worry about state being messed with. The outcome of each function is always the same so long as the function is called with the same parameters. In imperative programming as done in OOP, you can't depend on that. Unit testing each part doesn't guarantee that your code is bug free and secure because bugs can arise from the interaction of the parts even if every part is tested and passed. In functional programming, however, you never have to deal with that kind of problem because if you test that the range of each function is correct given the proper domain, and pre-screen the parameters being passed to each function to reject any out-of-domain parameters, you can know with certainty where your bugs come from by unit testing each function.

    If you need to guarantee the order of evaluation (something that critics of FP advocates sometimes use to dismiss FP advocacy), you can still use FP and benefit: in functional programming, order of evaluation can be enforced using monads. Explaining how is beyond the scope of a mere comment though, but in any case, if you need really reliable code, consider using a functional programming style.

    I can't do justice to the matter here; for more information, see th

    1. Re:The only sure way I know of: Lambda calculus by TheRaven64 · · Score: 4, Insightful
      When you start to introduce concurrency into a functional program, you end up with something closer to Pi calculus. The verification of both Pi and Lambda calculus expressions is still an open research problem (being worked on by some very bright people on the floor below me). There are a huge number of problems, not least of which in my mind is Gödel's incompleteness theorem, which states (roughly) that any system can only be completely described by a system more complicated than itself. You can generate a proof from your lambda program, but you still need to verify it and the proof will be more complicated (and thus harder to verify) than your original problem.

      There is also the question of what the proof actually says. You can't prove, for example, whether a lambda program will terminate (Halting Problem), and in fact you can prove that you can't prove this. If you have a sufficiently well expressed specification for your program, you can verify that the program and the specification match. Unfortunately, if you have a specification that concrete, you can just compile it and run it.

      By the way, Scheme is not a functional language. It has a number of properties that make it possible to write functional code, but saying Scheme is a functional language is like saying C++ is an object oriented language.

      --
      I am TheRaven on Soylent News
    2. Re:The only sure way I know of: Lambda calculus by Anonymous Coward · · Score: 2, Informative

      If you program using strictly functional programming, you can not only verify that your code is 100% secure, but you can even automate the process. You cannot write a program in a turing-complete language to determine if another program in a turing-complete language is 100% secure. It's trivially reducable to the halting problem. You can't automate it, at least not with 100% accuracy, in every case.

      Assume you have an algorithm (however complex) that can determine if a program in some turing complete language is secure, call it IsSecure(). IsSecure() is provably secure, because you've ran it on itself.

      Now, write a program that has a security hole if and only if IsSecure() returns true:

      #Program A
      start(input)
      {
              if(IsSecure(input))
                    ExposeSecurityHoleInSelf()
              else
                    #The hole must be in the function IsSecure(), which is silly, because you've used IsSecure() to secure IsSecure()
      }


      Call program A passing itself as input.
      Q.E.D.

    3. Re:The only sure way I know of: Lambda calculus by asuffield · · Score: 2, Informative
      You cannot write a program in a turing-complete language to determine if another program in a turing-complete language is 100% secure. It's trivially reducable to the halting problem. You can't automate it, at least not with 100% accuracy, in every case.


      Congratulations, you have won today's "Ignorant undergraduate misunderstanding of the Halting problem" prize.

      You're wrong on every significant point. You can write a program in a turing-complete language to determine if another program in a turing-complete language is 100% secure. The way that you specified implementing such a program is flawed. The Halting problem says that there exist certain ways to specify a problem which admit no solution, even though a solution to the problem exists. It does not say that there exist no alternative ways to specify the problem which do admit solutions. People always seem to think that the purpose of the Halting proof was to demonstrate that the real-world problem couldn't be solved - this is wrong. The purpose of the proof was merely to demonstrate that there exist certain non-trivial, interesting mathematical problem specifications which don't have solutions. This has interesting results in computability theory. It has very little relevance to the question of what sort of software we can write. It's all about how you reduce the real-world problem into a mathematical problem specification.

      Assume you have an algorithm (however complex) that can determine if a program in some turing complete language is secure, call it IsSecure(). IsSecure() is provably secure, because you've ran it on itself.

      Now, write a program that has a security hole if and only if IsSecure() returns true:

      #Program A
      start(input)
      {
                      if(IsSecure(input))
                                  ExposeSecurityHoleInSelf()
                      else
                                  #The hole must be in the function IsSecure(), which is silly, because you've used IsSecure() to secure IsSecure()
      }


      IsSecure returns false when passed this program as input. It doesn't matter that you think the answer is silly. This program is not secure because there exists a call to ExposeSecurityHoleInSelf in it and IsSecure failed to prove that this call was unreachable, or just didn't give a damn that it was unreachable. That is defined as an insecure program for the purpose of the IsSecure function. By specifying the problem in this way, we admit the possibility of a solution, and the Halting problem is avoided.

      In most cases, the Halting problem can be avoided in this manner. Nothing compels you to define your program as having no false positives.
      For the purposes of automated security validation, false positives are not a serious problem - we can easily write the program in a manner that can be proven secure by a given prover. We don't have to accept arbitrary programs as input.

      In practice, we don't do it like this. The function we use in the real world is is_proof_of_security_valid(), and it takes two inputs - a program and a proof of the program's security. The function checks that the proof is valid for this program. The proof itself is generated semi-automatically, but some parts are supplied by humans - typically via markup in the program's source (lint tags are a classic example of this sort of thing). It's much easier to write the thing this way.
    4. Re:The only sure way I know of: Lambda calculus by SheeEttin · · Score: 2, Funny
      You can't prove, for example, whether a lambda program will terminate (Halting Problem)
      If you're running Windows, no problem. It'll terminate within the first few hours.
    5. Re:The only sure way I know of: Lambda calculus by Coryoth · · Score: 2, Informative
      There are a few misconceptions here which deserve comment.

      You can't prove, for example, whether a lambda program will terminate (Halting Problem), and in fact you can prove that you can't prove this.

      This simply isn't the case - there are lots of programs for which you can easily prove termination. The catch with the Halting problem is that you cannot find a procedure that will work for all programs. In other words you may find yourself in a situation where you cannot prove termination for certain programs; that does not mean, however, that you can't prove termination for others, nor that such proofs are invalid. Trying to prove termination is far from futile - the Halting problem will at worst tell you that you might not be able to do it, but if you can (and often enough you can indeed) then the proof is perfectly valid.

      If you have a sufficiently well expressed specification for your program, you can verify that the program and the specification match. Unfortunately, if you have a specification that concrete, you can just compile it and run it.

      Again, this isn't quite true. Certainly, for some problems, an accurate specification will be equivalent in complexity to an implementation. On the other hand, there are a great many problems where that isn't the case. Take a specification for finding a square root (to within a specified error tolerance epsilon): given an input number x, the function must produce a value y such that abs(x - y*y) < epsilon. That's a complete specification (and it isn't hard to formalise that into a suitable specification language) but you certainly can't compile and run it and get anything useful - the actual implementation of how to find the square root is going to be more detailed, and quite important.

      Similarly we can specificy a sort function: given a list of items (comparable by '<') the function must return a list that is a permutation of the input list (that is, they contain the same elements), and such that for each list index i (except the index of the last element) result[i] < result[i+1]. Again, that's a complete specification for a sort function - it ensures that the function does indeed sort the list. On the other hand it is not compilable (except, maybe, into bogosort), and any particular sort implementation will have to use a specific sorting algorithm (be it quicksort, mergesort, or otherwise) which will be undoubtedly more complex than the simple specification given.
  26. Security? What's that? by JHWH · · Score: 2, Insightful

    You can write code that can be as secure as you want, but what about libraries, compilers and hardware?
    I think the question itself makes little sense without a deeper investigation in the system!

    --
    Intelligence has limits. Stupidity doesn't.
  27. By the way, I meant to say this also by Berkana · · Score: 3, Interesting
    If you want to learn about Lambda Calculus (which was developed by Alonzo Church, a contemporary of Allan Turing), Wikipedia is a good place to start (http://en.wikipedia.org/wiki/Lambda_calculus ), but mastering Lambda Calculus is not necessary; first master a functional programming language, and a lot of the lambda calculus will be made easier.

    To summarize, here's how you verify with mathematical certainty that a functional program is secure:
    1. You use purely functional code; that guarantees that there are no changes of state involved in the operation of your program.
    2. you unit test each function to make sure that given the correct domain/scope, their return values are always conforming to the desired range (and I don't just mean numbers when I say "range"; I mean correct data formatting, list/tree formatting, data structures, etc.), and you set up input filters that exclude any call parameters that are not part of your desired function domain.
    3. You check to see what functions call which functions, and make sure that they never call a function with parameters that are incorrectly formatted or out of the correct domain
    4. You make sure that every function and every constant is properly scoped.

    That's the gist of it. Anything more on this topic, such as automatic code auditing with the certainty of mathematical proofs (by means of lambda calculus proofs) is beyond my expertise. I just know that it's possible to truly secure functional code with mathematical certainty, whereas with imperative code, you can only be sure that your code has not yet failed or exposed a rare bug or failure condition.
  28. Re:Don't use C++ as if it was only "C with classes by shutdown+-p+now · · Score: 3, Informative
    Uh... let's see. Open the most recent ISO C++ standard, and search for all occurences of "undefined". Repeat for "implementation-defined". Make a notice of how many of those are from the sections related to the Standard Library. Then meditate on the results.

    Yes, sure, if you use STL, you need not worry about getting the buffer size wrong. And that's about it - container indexing is not bound-checked (unless you use at() instead of operator[] - and that's about the only instance of run-time safety check I remember seeing in STL!), iterators can go outside their container without notice, or can suddenly become invalid depending on what their container is and what was done to it. Even leaving library issues aside, there are some nasty things about the language itself - it's just way too easy to get an uninitialized variable or a class member, or to mess up with the order of field initializers in constructor.

    This is not to say that C++ is not a good language. All of the above are features in a sense they are there for a reason - but they certainly don't make writing secure software easier.

  29. Coding 101 by Tom · · Score: 4, Insightful

    We all know the answer if we've studied computer science. The problem is that the answer is boring, lots of work and totally non-hip.

    It's specifications, pre- and post-conditions, all that "theoretical bullshit" we learned in university. It's just that writing code that way is very un-exciting, and that's a vast understatement.

    --
    Assorted stuff I do sometimes: Lemuria.org
    1. Re:Coding 101 by Coryoth · · Score: 2, Insightful
      It's specifications, pre- and post-conditions, all that "theoretical bullshit" we learned in university. It's just that writing code that way is very un-exciting, and that's a vast understatement.

      That depends really. As a math geek I find a certain amount of pedantry and formlisation natural. I mean many people are happy to spend the extra time writing annotations to define types signatures for functions (and even types for variables in some languages) which is, really, just a light form of specification. Using Eiffel, or Java with JML, or Spec#, or D, really isn't as bad as you might think - you mostly end up writing things you'll have to get around to writing anyway (when it comes time to properly document APIs etc.), you just get to write it along with the code in a slightly more formal way...
  30. old versions of purify by joss · · Score: 2, Interesting

    Helped a lot for this kind of thing. The tool went downhill quite
    a long way but its still useful. Electric fence helps too.
    Then a lot of old fashioned software engineering.. use raw arrays
    as little as possible, add bounds checking to std::vector [] if you
    feel inclined, use gprof to identify any code not being excercised
    by your unit tests [you do have unit tests, right]. Lastly, actually
    read the darn code and make sure anytime you are using raw arrays
    you check the size.

    --
    http://rareformnewmedia.com/
  31. Half a solution by DoofusOfDeath · · Score: 3, Funny
    How Do You Know Your Code is Secure?

    Make it part of the critical path in music DRM. Then you know it's not secure.

    Not sure about the flip-side, though.

  32. Re:Don't use C++ as if it was only "C with classes by orangeyoda · · Score: 2, Funny

    Which is a good thing, Ada was awful to learn and worse to debug. I've seen the light, no more c++ spending hours to decode meglomaniac's tempalates , no more java exception hell , bye bye vb6 error unhandling . Hello C#

  33. If it compiles... by GroovBird · · Score: 2, Funny

    ...you can ship it.

    It's that simple!

  34. SPARK by Rod+Chapman · · Score: 5, Insightful

    For high-integrity stuff, we use SPARK (http://www.sparkada.com/) - a design-by-contract subset of Ada95 that is entirely designed-from-scratch for verification purposes.
    The verification system implements Hoare-logic and is supported by a theorem prover. Buffer Overflow is only one of many basic correctness properties that can be verified. Properties that can be verified are only limited to what can be expressed as an assertion in first-order logic.
    SPARK is a small language (compared to C++ or Java...) but the depth and soundness of verification is unmatched by anything like FindBugs, SPLINT, ESC/Java or any of the other tools for the "popular" languages.
    (If you don't know or care what soundness is in the context of static analysis, then you've probably missed the point of this post... :-) )
    - Rod Chapman, Praxis

  35. You know you're a geek when... by ruiner13 · · Score: 4, Funny
    You say things like:

    Mistakes will come back to byte you. without even flinching.
    --

    today is spelling optional day.

  36. Re:Don't use C++ as if it was only "C with classes by Metasquares · · Score: 3, Interesting

    Once you go outside of a container, you already have a fatal error and the appropriate response is to crash (albeit gracefully if possible). The problem isn't so much that the program crashes, but rather that the program may consider data outside of bounds as valid memory, thus allowing buffer overflows and undefined behavior to occur.

    The difference between pure C/C++ and the STL is that something like strcmp can create a rather subtle sort of buffer overflow error, whereas buffer overflows involving STL containers are generally easier to avoid and detect. For that matter, if you use the STL algorithms library to its full potential, you may find that you hardly ever need to use explicit indexing or iterators other than begin() and end().

  37. There are no good open source tools, unfortunately by Random+Walk · · Score: 2, Informative
    Although many (if not most) open-souce apps are written in C/C++, there are no really useful open source tools to check C/C++ code for security:
    • valgrind is very nice, but only reports memory corruption if it really occurs (i.e. you have to trigger the bug first). Not very useful to detect bugs.
    • splint doesn't understand the flow of control, thus it needs tons of annotations to work properly. A royal PITA if you work on existing code. Also, it just shifts the problem: how do you now prove that your annotations are correct? Besides, it produces tons of spurious warnings.
    • flawfinder, rats, et. al. just grep the code for suspicious functions like strcpy(). They don't understand C/C++, and thus produce warnings even in cases where it's perfectly clear that these functions are used safely.
    • some academic projects (like e.g. uno, ccured, ...) look interesting, but usually don't work on nontrivial code (at least not unless you are part of the development team and know the required wizardry to make them work). Also, most acedemic project go into limbo as soon as the thesis is written.
    I think one of the major problems is that commercial vendors like e.g. Coverity offer free service at least to major open-source projects, thus stifling any initiative to produce open-source counterparts of such tools.
  38. Re:Don't use C++ as if it was only "C with classes by Anonymous Coward · · Score: 2, Insightful

    TFA: "Especially if you have to write in a language like C or C++?"

    Why would you HAVE to use C or C+ or C*+**+++? I don't mean to be a troll, but if you are writing in an inherently insecure language (i.e., any compiled language) you aren't going to get secure code.

    OTOH of you write in, say, assembly, you are setting yourself up for the complexity. You have to make sure your buffers won't overflow, as opposed to leaving it to the compiler writers.

    As to overflows, if you KNOW your language is prone to overflowed buffers, it seems wise to check for overflows with your own code. After this long, there really is no excuse for buffers that overflow. It isn't hard to check for the length of a string, after all.

    If bridge engineers were as lazy as programmers, bridges would be falling down by the hundreds. My 1992 car is full of hundreds of thousands little bitty moving partsand fluids, but as long as I keep clean oil and filters in it, it doesn't break. My last car was an 1988, it lasted until last year. But I have to replace my 2002 Microsoft operating system because it's not secure? Somebody is making a lot of money off of poorly designed and poorly built software. There is no reason why I should have rto replace an OS.

    There are reasons for program errors, but no excuses. If your code is shit, it's shit because you wrote shit. Either you're incompetent or lazy. "You can have cheap, secure, or fast. Pick two."

  39. Re:Don't use C++ as if it was only "C with classes by swillden · · Score: 4, Informative

    whereas in a highly abstracted C++ program using the STL with lots of objects being copied and references flying around it can be a LOT harder to figure out whats really going on , especially since different compilers do different things under the hood.

    Those bugs aren't harder to track down than "old-style" bugs, in fact I think they're vastly easier to track down than, say, a wild pointer. The difference is that you're less experienced at dealing with the new problems, so they seem harder to you. With time and practice, you'll see through copy/reference errors quickly. In the meantime, a little discipline can cover your lack of experience -- never store raw pointers in collections, always "objects". If you don't want to create copies, then store objects of a smart pointer class. In fact, avoid ever using raw pointers at all. *Always* assign the result of a 'new' operation to a smart pointer (auto_ptr works for a surprisingly large set of cases, but you may have to get a reference counted pointer type or similar for others -- the BOOST library has some good options if you haven't already rolled your own).

    If you really run into different behavior with different compilers, then at least one of the compilers is buggy. That does happen, but it's a lot rarer today than it was a few years ago. When you find that situation, wrap the tricky bit behind another abstraction layer and implement compiler-specific workarounds so that your application code can just use the abstraction and get consistent behavior. In most cases, someone else has already done this work for you. Again, look into BOOST.

    --
    Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
  40. I doubt this guy's a security expert by ianalis · · Score: 2, Funny

    He's compiling as root :p

  41. Why would I want to? by jc42 · · Score: 2, Interesting

    I think it's a bad mistake to make your code secure. If you look at sales figures, you see that sales are inversely proportional to security. So customers don't want secure computer software. If they wanted that, they'd buy it. Clearly, what people want is the most insecure software they can get.

    I say go with The Market, and write the most insecure software you can. Securing your software will only waste your time and decrease your sales.

    --
    Those who do study history are doomed to stand helplessly by while everyone else repeats it.
  42. You cannot know. You can only engineer. by natoochtoniket · · Score: 2, Insightful

    I think it was Knuth who said, "In theory, theory and practice are the same. In practice, they are not."

    In theory, for any nontrivial program, you cannot know absolutely that it is secure. You cannot even know that it will terminate. The Turing showed that there is no algorithm which will decide if a program will halt. Most other problems of program behavior can be reduced to halting. (Just place a call to exit() immediately after the code that outputs the behavior in question.) In general, there is no way to prove that a program has any particular property that can be reduced to a termination property.

    The choice of language does not matter, either. Turing used a language that was very primitive, even compared with the simplest assembly languages. But Turing's language is equivalent in computing power to every modern general-purpose programming language. Church's completeness hypothesis is widely accepted as valid, though a proof in the strict sense cannot be written. So, Turing's mathematical proof of the halting theorem is valid for every modern programming language.

    There are some programs for which we do know that the program is correct. Such programs are all very small, solve well-defined mathematical problems, and are written in well defined functional programming languages. These proofs depend on very careful, mathematical definitions of the programming language, and of the function to be computed. The programming language is, strictly, an algebra. The proofs simply show that the algebraic formula (the program) transforms the algebraic input to the correct algebraic output. In every case, such proofs are quite difficult and tedious. And, as noted above, they are not possible in the general case.

    In practice, we can apply methods that are known as "engineering". That is, we can apply logic, design, inspection, review, and testing to develop some amount of confidence that it will behave as expected. But, engineering methods do not provide certainty. They only provide high confidence. The choice of language and tools have some effect on the ease or difficulty of doing the engineering work, but do not change the boundaries of what is possible.

    How do we "know" that a bridge will not fall down. There are no proofs of bridges. There is only engineering. Engineers apply logic, experience, design, inspection, reviews, and tests, so that they can have confidence in the design. The confidence is based on statistics. For a given shape of steel or concrete, we can measure loads that cause the steel to fail, and we can measure the variance in those loads due to the manufacturing tolerances of the material. When we use that shape and material to build the bridge, we can have statistics about how much load the bridge can support without failing. But even with all that engineering, sometimes bridges do fall down. The load measurements are only statistics, not proofs. There is always a confidence interval around every measurement, and the confidence can never be 100 percent.

    We can never have absolute proof of any property of any real, nontrivial program. We can have confidence as close to 100 percent as we want, if we spend enough effort on the engineering.

  43. For every string function by ebuck · · Score: 2, Interesting

    For ever string function, there's an equivalent that will only perform the operation on the first n bytes. If you're working with a C library that's old and doesn't have such a convienece, you can always wrap it with a call that does.

    The real problems come into play when you're using a 3rd party library. You can always police your code, but it's hard to police / fix other's code. Open source libraries are great for this in general, but there's not always an open source solution for connecting to proprietary buses, services, etc.

    In the end, solutions that require policing are only as good as policing. Policing is designed to only be effective after some atrocity has been committed, and so policing will likely only be effective after the exploit. A much better solution would prevent use of unbounded string functions by not having them defined. Perhaps there's some compiler magic that could be employed, but I doubt such techniques will gain much traction. It's like asking a guild of master carpenters to switch building materials. Once you know the materials and weaknesses, usually it's better to design around the weaknesses than to change materials.

    As a pratical real-world example near me, our school system just replace over a million bricks in a nearby school. The reason was that the new-fangled iodized metal bolts were used (way back when) to bind the bricks to the sub wall. Iodized was new and "hot" and it didn't rust, so the wall should have lasted forever. However, it corrordes when exposed to salt water, and the school was close enough to the sea to be exposed to salt water vapor. The problem was discovered when a worker leaned against a brick wall and it toppeled over.

    In the end, education will bring the current coders around, but don't expect the problem to go away. There will be many years of people reading antiquated "how to program" books that teach older, less safe, practices. There will be people reentering the marketplace that will have missed the newer techniques. There will be users installing from the copy of winZip (or whatever) that they downloaded in 2000.

    Only with time, and a whole lot of paitence, will this problem die. It won't be fixed, it will decline until it's barely noticable.

  44. Re:Don't use C++ as if it was only "C with classes by cnettel · · Score: 2, Insightful

    If you think that the flexibility and usefulness provided by C++ is present in Java or C#, then you are only using it as a nicer C.

  45. Re:Don't use C++ as if it was only "C with classes by Curien · · Score: 3, Informative

    And that's exactly why so many things are "implementation defined" or "undefined". Many real-world users of C++ demand that, for instance, vector::iterator be a typedef for a raw pointer for efficiency reasons. Other equally-important users would prefer an iterator type that guarantees sensible behavior in the face of real errors. The ISO standard allows for both behaviors by conforming C++ implementations.

    There's something attractive about the Java and C# languages having all constructs so well-defined. But both of those languages could afford not to support real hardware. Both target abstract machines and are happy with the results. C++ can afford no such conceit: it thrives in high-performance, customized, and otherwise exotic environments.

    --
    It's always a long day... 86400 doesn't fit into a short.
  46. Re:Don't use C++ as if it was only "C with classes by cnettel · · Score: 2, Informative

    Dynamic linking will also frequently create thunking tables close together, and lots of C code have other function pointer tables in special places anyway. (In a Win32 environment, you have that table for any COM object, it won't matter if you implement it in C, for example.)

  47. One more thing about OpenBSD by arthas · · Score: 3, Insightful

    Let's not forget their wonderful documentation! Complete and accurate API documentation is absolutely necessary for writing secure and reliable software. And of course the programmers should actually read the documentation and check all the details of the API calls they are using (return values, etc...)!

  48. Why bash C/C++? by DigitAl56K · · Score: 2, Insightful

    As a C/C++ developer I am a little offended by the article summary. Certainly C/C++ has a lot of flexibilities that allow bad developers to write bad code. However, many other languages, e.g. Java, allow bad programmers to write code that looks good because of stronger type checking, reduced use of pointers and the like. However, nothing stops a bad developer from writing insecure code in any language. Maybe you don't manage your resources correctly. Maybe you do a bad job of implementing encryption/protected storage. Maybe your authentication scheme is weak, your site is vulnerable to cross-site scripting vulnerabilities, or your session data can be easily spoofed.

    Secure code is not a product of language, it's a product of developers who take the time to fully understand the tools that they are using to build the product, including the ins and outs of their language of choice and its key risk elements, and who research risk elements for all other parts of the system.

  49. Re:Don't use C++ as if it was only "C with classes by CastrTroy · · Score: 2, Insightful
    If bridge engineers were as lazy as programmers, bridges would be falling down by the hundreds.
    I don't understand why people continually compare programming with building bridges, or cars. Until every programmer has a software engineering degree, and managers actually give them the time and resources to program correctly, then this is not a fair comparison. The reason that software fails so often is that it's rushed out the door before it's ready, or because the programmers are guys who took a 3 month course at a career college and now think they are programmers, and that they know what they are doing. Until the same care is taken designing software as it is to design bridges, they can't be compared. Bad software is not the fault of "lazy programmers", but rather the fault of companies hiring incompetent programmers, or not giving the competent ones the time and resources they need to do the job.
    --

    Anthropic principle: We see the universe the way it is because if it were different we would not be here to see it.
  50. Re:I don't. by peepleperson · · Score: 2, Funny

    Of course, everybody knows that yffect isn't a word. It's a small village in Wales.
  51. Re:Don't use C++ as if it was only "C with classes by yermoungder · · Score: 2, Informative

    FUD alert!!!

    C# might be appropriate for your domain but it certainly isn't in Ada's - safety critical or mission critical systems.

    It's also easy to learn as can be seen here http://www.stsc.hill.af.mil/crosstalk/2000/08/mcco rmick.html

  52. Re:Just Say No by iliketrash · · Score: 2, Insightful

    Ada is comparable to C and C++ in the area of "efficiency/performance." The misconception which you propagate disappears when fair comparisons are made. Remember that Ada is used in many embedded real-time applications; indeed, that is much of the reason that it came into existence in the first place.

  53. Re:Correct but irrelevant by Berkana · · Score: 2, Interesting

    They handle state in a scoped manner that is hard to describe without lots of example code. The best example I can think of is Erlang. If you look at the link I posted above (re-posted for your convenience: http://www.defmacro.org/ramblings/fp.html ) they mention Ericsson inventing the functional language Erlang to handle concurrency.

    As for how state functional languages handle state; state is held in the parameters a function is called with. The simplest example is recursion; in an imperative program using a for loop or a while loop or something like that, state is stored in a counter variable that gets incremented or decremented or somehow changed each time the loop is run. In recursion, if the ending condition is not met, the function calls itself with slightly differing parameters; the parameters keep track of the state, but unlike imperative programming, since the parameter is not a variable that can be changed once a call is made, it is impossible to have bugs caused by unexpected or unintentional changes to a variable in the scope of other operations that might change it. FP doesn't permit any declared values to change, so there are no "variables", just constants.

    If this makes no sense at all, you'll just have to program a few loops in an imperative language, and a few in a functional language using recursion, and see the difference. It's a lot easier to show interactively than to explain.

  54. Laws of construction by cheros · · Score: 2, Insightful

    Seems the process follows the laws of construction instead, as aggregated below:

    1 - measure with a micrometer
    2 - mark with chalk
    3 - cut with an axe
    4 - if it doesn't fit, use a larger hammer :-).

    --
    Insert .sig here. Send no money now. Owner may sue, contents will settle. Batteries not included.