Comments on proposed VVSG revisions 1: Exceptions

| Comments (0) | SYSSEC Voting
[See here]

S 5.2.2 requires that systems be written in programming languages which support block-structured exception handling:

The above requirement may be satisfied by using COTS extension packages to add missing control constructs to languages that could not otherwise conform. For example, C99[2] does not support block-structured exception handling, but the construct can be retrofitted using (e.g.) cexcept[3] or another COTS package.

The use of non-COTS extension packages or manufacturer-specific code for this purpose is not acceptable, as it would place an unreasonable burden on the VSTL to verify the soundness of an unproven extension (effectively a new programming language). The package must have a proven track record of performance supporting the assertion that it would be stable and suitable for use in voting systems, just as the compiler or interpreter for the base programming language must.

One could interpret this requirement as simply being that the language must support this functionality, not that it be used, in which case the requirement is unobjectionable. However, S 5.2.5 makes clear that programmers are expected to actually use exception constructs, which is significantly more problematic.

The first issue is that an exception-oriented programming style is significantly different than an error code-oriented programming style, so complying with the spirit of this requirement implies a very substantial rewrite of any existing system which uses error codes. However, experience with previous VVSG programming style requirements suggests that vendors will do the minimum required to comply with the letter of the VVSG. Because the two styles are similar enough that the conversion process can be done semi-mechanically, the likely result will be a a program which superficially works but which now has subtle bugs which were introduced during the conversion process.

One class of bugs that deserves particular attention is the proper cleanup of objects before function exit. When a function creates a set of objects and then encounters an error, it is important to clean up those objects before returning with the error. Failure to do so can leak memory and, more importantly, lead to improper finalization of objects which may be connected to non-memory resources such as network connections, hardware, etc. In languages such as Java, this is handled by garbage collection, but C is not garbage collected. Thus, when an exception is thrown from a function deep in the call stack and caught in a higher function, it bypasses all explicit cleanup routines in intermediate functions, which can lead to serious errors. Handling this situation correctly requires extreme care comparable to that required with conventional error handling. Writing correct code under these circumstances is challenging under the best of conditions, but is likely to be impractical under conditions where programmers are required to convert existing error code-based software.

While it might be the case that a completely new system written along exception-oriented lines would be superior, I am aware of no evidence that a retrofitted system would be superior and there is a substantial risk that it will be worse.

The second issue is that because C has no native exception handling, systems written in C will need to use a COTS package. Unfortunately, because exception handling is not a native feature of C, any attempt to retrofit it involves tradeoffs. As an example, the cexcept[3] package cited above, does not support conditional exception handling. In C++ exceptions, it is possible to have a Catch statement which only catches some exceptions, e.g.,

   try {
 

   }
   catch (memory_exception){
     ;
   } 
   catch (data_exception){
     ;
   }
 
   // Other exceptions get passed through
But in cexcept, a Catch statement catches exceptions of all types and you need to use an explicit conditional in order to discover which exception was thrown. But this creates much the same opportunity to ignore/mishandle unexpected exceptions that error codes do.

Another problem with cexcept is that it is very brittle whenever exception handling is intermixed with conventional error handling. Any function which jumps out of a try/catch block can result in "undefined" behavior (i.e., the implementation can do anything whatsoever). This, of course, is an easy mistake to make when converting from return codes to exceptions.

cexcept is not, of course, the only C exception package. For instance, Doug Jones has developed a different exception package, which makes different tradeoffs (though the above intermixed exception/return problem seems to exist here too).

Third, the use of the term "COTS" to cover these packages seems to require a fairly loose definition of COTS. While it is true that there are a number of exception packages available for free download, it is not clear to what extent they are in wide use by programmers. In my experience as a professional programmer, I have yet to work on a system written in C which used on of these packages. As the stated purpose of the COTS requirement is to be to ensure that the packages have seen enough deployment that we can have confidence in their quality, it seems questionable whether any of the available packages meet this standard.

Leave a comment