1. 7

UNIX programmers too often fail to check for failure of system calls or functions, taking the familiar teen-age attitude that ‘‘it can’t happen to me (or my program)’’. This paper will attempt to convince its audience to take prophylactic measures. Those who take such measures will be healthier − and less prone to surprises − than those who don’t take such measures.
In the tradition of the classic Elements of Programming Style some real-world pro-grams will be criticised publicly. Actual production (or soi-disant production) UNIX programs and subsystems will be examined. Each of these ‘‘provides one or more lessons in style.’’ We present both before and after versions of most code fragments. Come on out and see if we abuse one of your programs − or your programming style!

  1.  

  2. 4

    Ahhhh, assuming malloc can never fail predates Linux at least.

    1. 1

      His example code looks sane… checks and then promptly error aborts. Good.

      I often see convoluted malloc fail handling code that, somewhere in the callgraph (eg. printf), relies on malloc magically now suddenly succeeding.

      Sigh. It would be better to delete all that flaky useless shit and let the segfault catch it.

      1. 1

        Sigh. It would be better to delete all that flaky useless shit and let the segfault catch it.

        There may not have been a segfault at the time.

        Unix on the VAX, the follow-on to the PDP-11, used a similar scheme. The first two bytes of every VAX Unix program were zero (a register save mask saying not to save anything.) As a result, a null all-zero pointer was always valid, and if a C program used a null value as a string pointer, the zero byte at location zero was treated as a null string. As a result, a generation of Unix programs in the 1980s contained hard-to-find bugs involving null pointers, and for many years, Unix ports to other architectures provided a zero byte at location zero because it was easier than finding and fixing all the null pointer bugs.

        from Linkers and Loaders by John Levine

        1. 1

          Which is probably why his example checked and error’d.

          But in my life I found and deleted hundreds of lines of code that frantically…. and uselessly fails about attempting to handle a failed malloc… and the handling code was provably bogus.

    2. 3

      I think my favourite thing about these older writings is how they have the same complaints that show up now.

      The art of thinking (before you code) often seems a lost art. Such safeguards as validating the input before you read it and keeping the user interface constant from one command to the next, are good things whose time has not (we hope) truly passed.

      This is dated 1989, now 32 years old. I have read similar sentiments in writings from the 1960s and 1970s. I posit that thinking before you code was never an art that was in regular practice, that looking at the past with rose coloured glasses has been in fashion the whole time, and much of what we think programming used to be like (namely, how great it was) is largely made up.

      1. 3

        Give me a program that you say has a totally mysterious and impossible bug…

        The first thing I do is run around and check every return code.

        About 8 times out of 10 the problem becomes obvious.

        Avoid variable number of arguments in functions.

        Outdated advice. gcc and clang permit you to declare an attribute that will check for sanity. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-functions-with-printf_002c-scanf_002c-strftime-or-strfmon-style-arguments

        lint has been supplanted by -W -Wall -Werror, but latest gcc is taking it to the next level with -fanalyzer

        1. 2

          Avoid variable number of arguments in functions.

          Outdated advice. gcc and clang permit you to declare an attribute that will check for sanity

          If you notice, the advice has nothing to do with the security of variadic functions, but with the portability of the construct. (This piece is from 1985!) stdarg.h was standardized in c89.

          1. 3

            Ok, missed that!

            I was mostly looking at his maxims not the details behind them and seeing if they still hold.

            His “assume syscalls fail capriciously”, no they don’t, they fail for very sound and well defined reasons…. but the one people often miss is EINTR.

            If you’re not checking for and handling it when it is possible… you have a bug, plain and simple…. and it’s a very commonly reoccuring bug!

            1. 3

              His “assume syscalls fail capriciously”, no they don’t, they fail for very sound and well defined reasons

              Defensive security means assuming that all components of a system will fail; that includes the ones you wrote, the ones you didn’t write, and even ‘untouchables’ like hardware memory protections and the os kernel. Sure, there are reasonable limits; but looking at the return value of a syscall is a reasonable sanity check that guards against both kernel bugs and bugs (or misunderstandings!) in your own code; and the cost (when compared with the cost of the syscall itself) is negligible.

          2. 1

            lint has been supplanted by -W -Wall -Werror, but latest gcc is taking it to the next level with -fanalyzer

            I don’t think this is quite right. Certainly the diagnostics in newer compilers are increasingly good, and GCC has been driven to improve by competition from Clang – but when we dropped lint from the illumos build we replaced it with a similar tool, smatch, from the Linux ecosystem. It checks a lot of possibly more heuristic things like lint did, and is definitely not wholly obviated by the warnings in the compiler.

            1. 1

              smatch

              I was more saying that everything lint and it’s direct descendent splint (except maybe ownership annotations) is now done better by the compiler warnings.

              But yes, there are other tools available as well now…. but they are sort of looking at different things to what lint was.