Index  Comments

This article was spurred by ``Infectious Executable Stacks''.

The author of the article being rebutted begins by decrying an unnecessarily complicated thread edge case, variable-length arrays, and memory aliasing in the context of C. In order: this is due to the poor POSIX semantics regarding the failure of system calls, which can occur for most any reason, and the insufficient signal mechanism, combined with how the C lacks anything resembling the Common Lisp UNWIND-PROTECT; the issue with variable-length arrays is, as with many other things, that C performs no safety checks of any kind and also lacks anything resembling a memory exhaustion exception, along with any exception system at all; and the issues with memory aliasing come from C both requiring the overuse of pointers and requiring most variables have addresses, unlike Ada. Simply put, the author has written several articles concerning how C is supposedly efficient and simple, despite knowing of all of these grotesque and bizarre misfeatures and pitfalls laying about.

Moving on, the article being rebutted concerns memory which is both writeable and executable and how this is supposedly a bad thing. Apparently, GNU C implements its nested functions extension using a stack trick which requires the stack memory to be executable; this is considered bad due to how easy the C language makes catastrophic program failure. The author continues, to deem this default being a ``fail open design'' and how he failed to notice this for years in one of his programs.

I can easily envision a design of closures that doesn't require the stack trick, but can only figure this is imposed by some constraint regarding the compiled output and also how C isn't built for such simple features as closures. In any case, a program which suffers memory errors is horribly broken, regardless of whether that memory is or isn't also executable. That this would seriously be used as a security feature intended to prevent nigh-inevitable memory errors from becoming worse, as opposed to an optional layer of a security system, is a general indictment of C. Further, the impact of the restrictions imposed severely disadvantage programs which generate machine code as they execute, but this is usually dismissed as being uncommon.

In closing, I consider such restrictions a good example of the C attitude of, rather than aiming for a correct program, taking great effort to add layers of defense that are still trivially bypassed by a single mistake, as opposed to simply using a language which entirely eliminates the class of flaw.