Article development led by
Finding and fixing bugs in deployed
software is difficult and time-consuming.
Here are some alternatives.
By emeRy D. BeRGeR
liKe DeaTh aND taxes, buggy code is an unfortunate
fact of life. Nearly every program ships with known
bugs, and probably all of them end up with bugs
discovered only post-deployment. There are many
reasons for this sad state of affairs.
one problem is that many applications are
written in memory-unsafe languages. Variants of
C, including C++ and objective-C, are especially
vulnerable to memory errors such as buffer overflows
and dangling pointers (use-after-free bugs). Two of
these are in the SANS Top 25 list: buffer copy without
checking size of input ( http://cwe.mitre.org/top25/
index.html#CWE- 120) and incorrect calculation
of buffer size ( http://cwe.mitre.org/top25/index.
html#CWE-131); see also heap-based buffer overflow
html) and use after free (http://cwe.mi-
These bugs, which can lead to crashes, erroneous execution, and security
vulnerabilities, are notoriously challenging to repair.
Writing new applications in memo-ry-safe languages such as Java instead
of C/C++ would help mitigate these
problems. For example, because Java
uses garbage collection, Java programs
are not susceptible to use-after-free
bugs; similarly, because Java always
performs bounds-checking, Java applications cannot suffer memory corruption caused by buffer overflows.
That said, safe languages are no
cure-all. Java programs still suffer from
buffer overflows and null pointer deref-erences, although they throw an exception as soon as they happen, unlike
their C-based counterparts. The common recourse to these exceptions is to
abort execution and print a stack trace
(even to a Web page!). Java is also just
as vulnerable as any other language to
concurrency errors such as race conditions and deadlocks.
There are both practical and technical reasons not to use safe languages.
First, it is generally not feasible to rewrite existing code because of the cost
and time involved, not to mention the
risk of introducing new bugs. Second,
languages that rely on garbage collection are not a good fit for programs that
need high performance or that make
extensive use of available physical
memory, since garbage collection always requires extra memory. 6 These include operating-system-level services,
database managers, search engines,
and physics-based games.
While tools can help, they cannot
catch all bugs. Static analyzers have
made enormous strides in recent years,
but many bugs remain out of reach.
Rather than swamp developers with
false positive reports, most modern
static analyzers report far fewer bugs
than they could. In other words, they
trade false negatives (failing to report
real bugs) for lower false positive rates.