University of London CM 2010 Software Design and Development
Opinion 1: Always use assertions
Opinion 2: In industry, assertions are often removed in release builds
For a great discussion of various aspects: What are assertions?
Assume in runtime assertion where the program is running. Other types of assertions: unit tests, compile-time assertions.
An assertion is a check in your code that evaluates a boolean expression. It checks whether the program is in a desirable state.
int gameScore;
...
assert(gameScore >= 0);
An if
statement controls the flow of the program;
An assertion
checks the state.
What should you do if a run-time assertion fails?
Terminate the program
We might not want to terminate the whole program if it’s something multiple users are using at once.
Print an error
If writing a library, we can’t predict what it’s been used for hence the error message might not make sense.
Throw an exception
A pretty good way to deal with assertion failure. The part of the program calling the code might not be able to handle it.
Carry on regardless
Test that the loop has not iterated more than 10,000 times.
Before devision operation, check you are not dividing by zero.
Release build: remove all/dmost assertions from debug build to save runtime (opinionated)
Debug build
#include <cassert>
int main() {
double sensorReading = 65537;
unsigned short storedValue = sensorReading;
assert(storedValue == sensorReading);
return 0;
}
sensorReading = 65000
storedValue = sensorReading+1
assert(storedValue == sensorReading)
const assert = require("assert");
let sensorReading = 65500;
let storedValue = sensorReading+1;
assert(storedValue == sensorReading);
(PDF) Classic paper from 1975: Saltzer, J.H. and M. D. Schroeder ‘The protection of information in computer systems’, Proceedings of the IEEE 63(9) 1975, pp.1278–308.
(PDF) David Wheeler’s book is a great resource. It is Unix focused but applicable to all platforms: Wheeler, D.A. Secure programming for Linux and Unix HOWTO (1999).
Some interesting articles can be found in Security and Privacy.
(PDF) For an analysis of software companies’ approach to secure software, read Geer, D. ‘Are companies actually using secure development life cycles?’, Computer 43(6) 2010, pp.12–16.
Links:
Comprehensive, Lightweight Application Security Process (CLASP)/Open Source Foundation for Application Security (OWASP): Introduction to the CLASP process
Security goals
Sucure Programming Hit List
Validate All Input
Ex. Keyboard presses, files read from disk, data passed to a function, data received over a network.
Restrict Operations to Buffer Bounds
Ex. Heartbleed causes buffer bounds (overflow), Wannacry from North Korea, The internet worm had a buffer overflow attack component.
Follow Good Security Design Principles
From The protection of information in computer systems
Carefully call out to other resources
Ex. Library routines, databases, external programs.
Send information back judiciously
Being careful about what’s been sent back to the users.
Ex. Passwords being printed out, debug print outs.
…a structure for the various software development activities to be performed within a project.
i.e. test-driven development
Microsoft Security Development Lifecycle (SDL)
…consists of a set of practices that support security assurance and compliance requirements. It helps developers build more secure software by reducing the number and severity of vulnerabilities in software, while reducing development cost.
Alternatives to MS SDL
SAMM: an open framework to help organizations formulate and implement a strategy for software security that is tailored to the specific risks facing the organization.
BSIMM (“bee simm”): a study of existing software security initiatives. By quantifying the practices of many different organizations, we can describe the common ground shared by many as well as the variations that make each unique. It is not a how-to guide, nor a one-size-fits-all prescription, it is a reflection of software security.
CLASP/OWASP: designed to help software development teams build security into the early stages of existing and new-start software development life cycles in a sturctured, repeatable, and measurable way.
pip install bandit
Testing third-party libraries
bandit *.py
to test all .py files in that library (bandit -r .
if the command doesn’t work)bandit -ll *.py
to show only medium & high severity (bandit -rll .
works)
Event that causes suspension of normal program execution
Indication that an operation request was not performed successfully
The foundamental idea is to separate detection of an error (which shuold be done in a called function) from the handling of an error (which should be done in the calling function) while ensuring that a detected error cannot be ignored.
Bjarne Stroustrup - Programming: principles and practice using C++, 2014
logical expression specifying a program state that must exist or a set of conditions that program variables must satisfy at a particular point during program execution.
function or macro that complains loudly if a design assumption on which the code is based is not true
Assertion vs. Exception
Exceptions should be used to catch errors, control flow has similar syntax and function, but shouldn’t be used as such.
Try and catch
try {
verifyUser();
console.log('After verifyUser');
} catch (ex) {
console.log('Exception caught');
console.log('Name: ' + ex.name);
console.log('Message: ' + ex.message);
}
console.log('I am still running...');
Exception Handling in JavaScript (code)
Here is a reference for the built-in errors in JavaScript:
Can you write an example program that generates one of these errors in JavaScript?
Debugging is simply the process of removing errors from your code. A debugger is a tool that you can use to inspect your program as it is running.
Using print
, console.log
, and std::cout
are a kind of manual debugger.
Debugger allows dynamic analysis.
Here is an advanced article which summarises some of the state of the art work circa 2016 regarding debugging:
(PDF) Wong, W.E., R. Gao, Y. Li, R. Abreu and F. Wotawa ‘A survey on software fault localization’, IEEE Transactions on Software Engineering 42(8) 2016, pp. 707-740.