LWN.net Logo

CERT C Secure Coding Standard: last call for reviewers

CERT C Secure Coding Standard: last call for reviewers

Posted Mar 17, 2008 1:31 UTC (Mon) by wahern (subscriber, #37304)
In reply to: CERT C Secure Coding Standard: last call for reviewers by nix
Parent article: CERT C Secure Coding Standard: last call for reviewers

What do you mean by "unlikely"? If you mean to say that the scenarios where one fails and the
other doesn't, then of course there are differences. But, I fail to see how that means they
should be treated different when they fail.

Noting this distinction is part of the original faulty logic, which is that a prerequisite
condition of managing malloc() failure is that the why's and how's need be somehow discernible
by the application, otherwise its a futile endeavour. Ostensibly, this is so the application
can "fix" them, or alter its behavior according to the specific reasons. I don't... it's hard
to discern the motivations or intentions in that line of argument. I can't see how the
requirement of "keep running" is conditioned on whether MySQL has a memory leak, because a
user just loaded a 200MB tiff image in Firefox, or because the /tmp partition filled up.

A robust application, by definition, should handle any _potentially_ transient failure
regardless of the underlying cause, generally speaking (there are myriad exceptions, of
course). A robust application can and should strive to remain internally consistent and
stable. Arguing that handling malloc() different from fopen() because one condition holds true
for malloc() 90% of the time, but only 10% of the time for fopen(), makes absolutely no sense
in a general context. And general context is what we're talking about: the proper practice for
handling malloc() failure.

What might be 10% or 90% generally might be 1% or 100% for any particular user or environment.
Different users experiencing wildly different behavior from software is one of the stains on
the industry, and its specifically because of these dependencies on unwarranted assumptions
and distinctions. Bugs will happen, and reasonable people can argue about what's easy or
difficult, but its ludicrous when the intentional practice is defended.

Once an application has hit a steady state (if it's that sort of application, like a desktop
application, server daemon, or even a really long lived data processor, etc), malloc() failure
should never cause it to exit. Even if it has a watchdog to restart it, these are the types of
applications which juggle multiple tasks, and which the unnecessary loss of state creates
gigantic headaches; they demand internal isolation of all reasonable errors. And arguing that
handling a malloc() failure is unreasonable doesn't hold water, particularly after the
application has already enough committed resources to subsist. This almost never requires
keeping "emergency" memory buffers or any other tricks; I've never had to resort to such
things. It's the proverbial case of throwing the baby out with the bath water.

Imagine, for instance (with the infamous exception of glib) libraries exiting like this? If
OpenSSL crashed your application because it couldn't initialize an internal resource?  OpenSSL
is an incredibly complex piece of software; probably too complex, with lots of cruft. But they
manage to do this "impossible" task, and don't resort to making distinctions between this
resource or that resource. It propagates the condition to the appropriate level, which is the
portion of code which decides whether its remainder can proceed with the failure of the
_logical_ task, and (similar to the issue above), not based on why, specifically, it failed.
And because of the miracle of componentization and abstraction, the problem of handling
malloc() failure becomes identical to handling any of the other potential failure conditions.
And unless you can make a case in a particular instance for bailing on all such errors, why
bail on only some of them?




(Log in to post comments)

CERT C Secure Coding Standard: last call for reviewers

Posted Mar 20, 2008 15:13 UTC (Thu) by paulj (subscriber, #341) [Link]

The simplest and most reliable error-strategy often is to restart, surely? Optimising restart
has benefits for more than just error-handling too.

The obvious example would be malloc() failing because the application itself is leaking
memory. No amount of retrying malloc() will help there. Restarting will however at least
mitigate the problem, allowing the user to continue to use the system, until the software can
be fixed to address the leak.

Copyright © 2008, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds