I think there is a fairly convincing argument here that a lot of these bugs might not have occurred if Bash used a hand-written, recursive-descent parser instead of a Yacc autogenerated one:<p>- The original ShellShock: Reused the general parsing/execution function for the subset task of evaluating a function definition. A hand-written parser would likely have this isolated to its own function. With a Yacc parser, there is neither an obvious nor easy way to call directly into the parser to parse a "nonterminal".<p>- The ones in the article having to do with error handling: traditionally, error handing in autogenerated parsers has been more difficult and Yacc is no exception. This is related to the first point in that a function for only parsing the function definitions would never execute its input, even upon encountering an error; the usual abort behaviour means the parser stack unwinds until the original caller - in this case the code parsing environment variables for function definitions - recognises the error, outputs an error message, and in this case, ignores the definition.<p>- The operation of a recursive-descent parser is simpler to trace through manually since each piece of the grammar is logically broken into separate functions, making it easier to audit than the more opaque flow of a Yacc one.