[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.