Software Construction: Assignment 3 (Worth 100 Points)
NDSU CSCI 717 Software Construction
Defensive Programming
Textbook
Steve McConnell. Code Complete: A Practical Handbook of Software Construction. 2nd Edition. Microsoft Press, 2004. Chapter 8.
2
Outline
Protecting from Invalid Inputs
Barricade/Firewall Your Program
Be Defensive about Defensive Programming
3
Protecting from Invalid Inputs
Garbage in, garbage out?
Mark of sloppy nonsecure program
Garbage in, nothing/error message out
No garbage allowed in
Defensive programming
If a routine is passed bad data, it won’t be hurt, even if the bad data is another routine’s fault.
Check values of all data from external sources
Sources: file, user, network
Allowable range: String vs security problem
Check values of all routine input parameters
Decide how to handle bad inputs
4
Assertions
To document assumptions made in the code and to flush out unexpected conditions
An input/output parameter in its expected range
A file/stream is open (or closed) when a routine begins (or ends) executing
A file/stream is at the beginning
A file/stream is open for read-only, write-only, etc.
An input-only variable is not changed
A pointer is non-null
A container is empty (or full) when a routine begins (or ends) executing
Match two results
5
Assertion Mechanism
Java assertions
Assert denominator!=0 : “denominator is 0”
Define your own
#define ASSERT(condition, message) {
if (!(condition)) {
LogError(“Assertion failed: ”, #condition, message);
exit(EXIT_FAILURE);
}
}
6
Using Assertions: Guidelines
Use error-handling for conditions you expect to occur; use assertions for condition that should never occur
Error handling typically checks for bad input
Assertions check for bugs in the code
Avoid putting executable code into assertions
The compiler will eliminate the code when the assertions are turned off
Use assertions to document/verify pre/postconds
For highly robust code, assert and then handle the error anyway.
E.g. change an invalid input to the closest legal value
7
Error-Handling Techniques
Return a neutral value (known to be harmless)
Examples: 0, empty string, default color
Substitute the next place of valid data
Encounter a corrupted record when reading from a DB
Return the same answer as the previous time
Thermometer-reading code does not get a reading one time
Substitute the closest legal value
Log a warning message to a file
Return an error code
8
Error-Handling Techniques
Call an error processing routine/object
Centralize error handling in a global routine/object
Display an error message wherever the error is encountered
Handle the error in whatever way works best locally
Individual developers have the flexibility
Risky: spread UI code throughout the system
Shut down
Safety critical applications
9
Using Exceptions: Suggestions
Use exceptions to notify other parts about errors that should not be ignored
Throw an exception only for conditions that are truly exceptional
Cannot be addressed by other coding practices
Don’t throw an uncaught exception if you can handle the error locally
Avoid throwing exceptions in constructors /destructors unless you catch them in the same place
The rule for how exceptions are processed become very complicated
C++: destructors are not called unless an object is fully constructed
10
Using Exceptions: Suggestions - cont
Throw exceptions at the right level of abstraction
The exceptions thrown are part of the interface
Class Employee {
public TaxId GetTaxId() throws EOFException
public TaxId GetTaxId() throws EmployeeDataNotAvailable
}
Include in the exception message all info that led to the exception
Avoid empty catch blocks
Know the exceptions your library code throws
Consider building a centralized exception reporter
Standardize your project’s use of exceptions
Consider alternatives to exceptions
11
Barricade/Firewall Your Program
A building’s firewall prevents fire from spreading from one part of the building to another part
Barricade your program to contain the damage caused by errors
Designate certain interfaces as boundaries to safe areas
Check data crossing the boundaries of a safe area for validity, and respond sensibly if the data is invalid
Class Level
Public methods assume the data is unsafe
Private methods can assume the data is safe
12
Debugging Aids
Introduce debugging aids early
Don’t automatically apply production constraints to the development version
Differences: speed, resource, etc
Use offensive programming
Exceptional cases should be handled in a way that makes them obvious during development and recoverable when production code is running. (Howard & Leblanc 2003, Writing secure code)
Default clause of case statement
Development - warning: “hey, another case here! Fix it”
Production - something more graceful, e.g. error-log
Plan to remove debugging aids
13
Programming Offensively
Make sure asserts abort the program
Don’t allow programmers to get into the habit of just hitting the Enter key to bypass a known problem
Completely fill any memory allocated to detect memory allocation errors
Completely fill any files/streams allocated to flush out any file-format errors
Be sure the code of default/else clause fails hard (aborts the program) or is o.w. impossible to overlook
Fill an object with junk data just before it is deleted
…
14
Be Defensive about Defensive Prog.
Think about where you need to be defensive.
Set you defensive programming priorities accordingly.
15