|
Packit |
1470ea |
|
|
Packit |
1470ea |
xmlns:its="http://www.w3.org/2005/11/its"
|
|
Packit |
1470ea |
xmlns:xi="http://www.w3.org/2003/XInclude"
|
|
Packit |
1470ea |
type="topic"
|
|
Packit |
1470ea |
id="preconditions">
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<info>
|
|
Packit |
1470ea |
<link type="guide" xref="index#specific-how-tos"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<credit type="author copyright">
|
|
Packit |
1470ea |
<name>Philip Withnall</name>
|
|
Packit |
1470ea |
<email its:translate="no">philip.withnall@collabora.co.uk</email>
|
|
Packit |
1470ea |
<years>2015</years>
|
|
Packit |
1470ea |
</credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<include href="cc-by-sa-3-0.xml" xmlns="http://www.w3.org/2001/XInclude"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<desc>Contract programming with checks on function input and output</desc>
|
|
Packit |
1470ea |
</info>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<title>Pre- and Post-Conditions</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="pre-and-post-conditions">
|
|
Packit |
1470ea |
<title>Pre- and Post-Conditions</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
An important part of secure coding is ensuring that incorrect data does
|
|
Packit |
1470ea |
not propagate far through code — the further some malicious input can
|
|
Packit |
1470ea |
propagate, the more code it sees, and the greater potential there is for
|
|
Packit |
1470ea |
an exploit to be possible.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A standard way of preventing the propagation of invalid data is to check
|
|
Packit |
1470ea |
all inputs to, and outputs from, all publicly visible functions in a
|
|
Packit |
1470ea |
library or module. There are two levels of checking:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<terms>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
<title>Assertions</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Check for programmer errors and abort the program on failure.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
<title>Validation</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Check for invalid input and return an error gracefully on failure.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
</terms>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Validation is a complex topic, and is handled using
|
|
Packit |
1470ea |
<link xref="gerror">GErrors</link>. The remainder of this section
|
|
Packit |
1470ea |
discusses pre- and post-condition assertions, which are purely for
|
|
Packit |
1470ea |
catching programmer errors. A programmer error is where a function is
|
|
Packit |
1470ea |
called in a way which is documented as disallowed. For example, if
|
|
Packit |
1470ea |
NULL is passed to a parameter which is documented as
|
|
Packit |
1470ea |
requiring a non-NULL value to be passed; or if a negative
|
|
Packit |
1470ea |
value is passed to a function which requires a positive value. Programmer
|
|
Packit |
1470ea |
errors can happen on output too — for example, returning NULL
|
|
Packit |
1470ea |
when it is not documented to, or not setting a GError output when it
|
|
Packit |
1470ea |
fails.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Adding pre- and post-condition assertions to code is as much about
|
|
Packit |
1470ea |
ensuring the behavior of each function is correctly and completely
|
|
Packit |
1470ea |
documented as it is about adding the assertions themselves. All assertions
|
|
Packit |
1470ea |
should be documented, preferably by using the relevant
|
|
Packit |
1470ea |
<link xref="introspection">introspection annotations</link>, such as
|
|
Packit |
1470ea |
(nullable) .
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Pre- and post-condition assertions are implemented using
|
|
Packit |
1470ea |
<link href="https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-if-fail">g_return_if_fail() </link>
|
|
Packit |
1470ea |
and
|
|
Packit |
1470ea |
<link href="https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-val-if-fail">g_return_val_if_fail() </link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The pre-conditions should check each parameter at the start of the
|
|
Packit |
1470ea |
function, before any other code is executed (even retrieving the private
|
|
Packit |
1470ea |
data structure from a GObject, for example, since the GObject pointer
|
|
Packit |
1470ea |
could be NULL ). The post-conditions should check the return
|
|
Packit |
1470ea |
value and any output parameters at the end of the function — this requires
|
|
Packit |
1470ea |
a single return statement and use of goto to
|
|
Packit |
1470ea |
merge other control paths into it. See
|
|
Packit |
1470ea |
<link xref="memory-management#single-path-cleanup"/> for an example.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<comment>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
FIXME: Incorporate content from
|
|
Packit |
1470ea |
https://tecnocode.co.uk/2010/12/19/postconditions-in-c/.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
FIXME: Mention breaking on criticals and warnings as a debugging tactic,
|
|
Packit |
1470ea |
using G_DEBUG=fatal-warnings, etc. Link to relevant GLib documentation.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</comment>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</page>
|