BLOG@CACM
Computing Applications

Run-Time Assertions: What Are You Waiting For?

Posted
Bertrand Meyer

A comment on the ACM forum comp.risks provides — as in the last article — a good starting point for reflecting about techniques of software quality.

In the latest issue of RISKS, Henry Baker comments [1] on an online article by David Wheeler [2] about "how to prevent the next Heartbleed", referring to the recently uncovered planetary-scale Internet vulnerability.

Both articles advocate the use of run-time assertion monitoring (Wheeler with some reservations) and both achieve the remarkable feat of not citing the one environment, Eiffel, in which run-time assertion monitoring has been routinely practiced for decades. Whether using Eiffel would have avoided the particular bug that led to Heartbleed can only be surmised, but for the users who daily apply techniques of Design by Contract (for a recent paper documenting practical usage see [3]), this is no speculation: run-time assertion monitoring catches bugs left and right.

Baker inexplicably opposes run-time assertion monitoring to proofs. He writes:

Unfortunately, proving that [

a] software system faithfully implements the model is undecidable for essentially every interesting system.

This means that it is hopeless to expect any language or compiler or type-checking system to be able to a priori guarantee faithfulness for all inputs.

and further:

Formal analysis can’t be used to prove the program correct,

 I am afraid Mr. Baker should refresh his understanding of undecidability (or perhaps improve the phrasing of his comments if that is the problem). What is impossible is to devise a general mechanism that could prove any contract-annotated (assertion-equipped) program. That does not prevent the mechanical proof of specific programs. The many researchers — and, increasingly, practitioners — using proof tools to perform mechanical verification of ever more ambitious programs would be surprised to learn that their work is impossible. Two examples of modern proof tools include Spark from Altran Praxis, which has proved the correctness of deployed life-critical systems, and Microsoft Research’s Boogie on which the AutoProof environment for Eiffel relies.

Indeed static verification and dynamic assertion monitoring are complementary. Sometimes proof is possible (always, in today’s technology, after a significant human effort to guide the proof process). Sometimes it fails. In the latter case, dynamic assertion monitoring is the solution; as Mr. Baker writes, one should

document

every assumption with aggressive run-time assertions.

He is right on target. This approach is what my articles and books have advocated for a long time and what Eiffel users apply. We are not just talking of assertions sprinkled here and there through the code — in the style of C or Java "asserts" or JUnit assertions — but contracts. The difference is that these contracts are intricately woven into the fabric of the code, appearing not just as consistency checks but as elements of specification associated with the structural elements of the design: routines (preconditions, postconditions), loops (loop invariants and variants), classes (class invariants). As a result, they are an integral part of the software construction process, from requirements through design and documentation to implementation, maintenance and verification. I am writing  "verification" and not just "testing" because verification takes many forms, some static, some dynamic.

One of the reasons one should not just use occasional assertions but contracts integrated in the structure of the code and the software construction process is the importance of change in software development. When programs are updated, as will always happen, it is hard to ensure that the developers will always insert new checks are inserted and update old ones as needed. When preconditions, postconditions, class invariants and other structural elements are an integral part of the software, it is far easier to enforce the discipline of updating specification and implementation together.

In dominant Eiffel practice, contracts are mostly used (in their verification role) for dynamic monitoring, exactly in the way suggested by Mr. Baker. The day is getting closer when they will be routinely combined with static proof tools; for an example of how such integration works, see references on EVE, the Eiffel Verification Environment, beginning with the original presentation in [4].

Wheeler also mentions run-time assertion verification, but states that

This approach does have some weaknesses when it comes to countering Heartbleed. Neither the original developer nor its reviewer realized that checking the request packet length value was important; since the length check was not included, it is unlikely that the developer would have remembered to add assertions to check for it.

Here too the difference between ordinary run-time checks and contracts is essential. What people miss when they have not actually practiced Design by Contract is that we are not just putting a few sporadic sanity checks. We are enabling programmers to develop their design and code from explicitly stated specifications. The approach often leads to uncovering assumptions that, as in the Heartbleed case, are critical to the correctness of the program but risk being  overlooked.

Then we enforce these assumptions; for example, dynamically.

References

[1] Henry Baker: Heartbleed and Formal Methods, in Risks Forum 27.89, 7 May 2014, ed. Peter G. Neumann, available here.

[2] David Wheeler: How to Prevent the Next Heartbleed, revised 11 May 2014, available here.

[3] H.-Christian Estler, Carlo A. Furia, Martin Nordio, Marco Piccioni, and Bertrand Meyer: Contracts in Practice, to appear (this week) in FM 2014, Proceedings of 19th International Symposium on Formal Methods, Singapore, May 2014, draft available here.

[4] Julian Tschannen, Carlo A. Furia, Martin Nordio, and Bertrand Meyer: Usable Verification of Object-Oriented Programs by Combining Static and Dynamic Technique, in in SEFM 2011, Software Engineering and Formal Methods, Montevideo, 14-18 November 2011, Lecture Notes in Computer Science, Springer Verlag, 2011, with a version available here

Join the Discussion (0)

Become a Member or Sign In to Post a Comment

The Latest from CACM

Shape the Future of Computing

ACM encourages its members to take a direct hand in shaping the future of the association. There are more ways than ever to get involved.

Get Involved

Communications of the ACM (CACM) is now a fully Open Access publication.

By opening CACM to the world, we hope to increase engagement among the broader computer science community and encourage non-members to discover the rich resources ACM has to offer.

Learn More