This required moving files around in the repository and shifting from a master.adoc structure to _topic_map.yml, etc. README and Makefile modified slightly to reflect new build process
425 lines
No EOL
20 KiB
HTML
425 lines
No EOL
20 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
|
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Library Design</title>
|
|
|
|
<!-- Bootstrap -->
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
|
|
|
<!-- Overpass Font -->
|
|
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
|
|
|
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
|
|
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
|
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
|
<meta content="AsciiBinder" name="application-name">
|
|
</head>
|
|
<body>
|
|
<div class="navbar navbar-default" role="navigation">
|
|
<div class="container-fluid">
|
|
<div class="navbar-header">
|
|
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="container">
|
|
<p class="toggle-nav visible-xs pull-left">
|
|
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
|
</p>
|
|
<ol class="breadcrumb">
|
|
<li class="sitename">
|
|
<a href="../../../index.html">Home</a>
|
|
</li>
|
|
<li class="hidden-xs active">
|
|
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
|
</li>
|
|
<li class="hidden-xs active">
|
|
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
|
</li>
|
|
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
|
<li class="hidden-xs active">
|
|
Library Design
|
|
</li>
|
|
</ol>
|
|
<div class="row row-offcanvas row-offcanvas-left">
|
|
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
|
<ul class="nav nav-sidebar">
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
|
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
|
</a>
|
|
<ul id="topicGroup0" class="collapse in list-unstyled">
|
|
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
|
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
|
</a>
|
|
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
|
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
|
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
|
</a>
|
|
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
|
<li><a class=" active" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
|
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
|
</a>
|
|
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
|
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
|
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
|
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
|
<div class="page-header">
|
|
<h2>Library Design</h2>
|
|
</div>
|
|
<div id="preamble">
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Through this section, the term <strong>client code</strong>
|
|
refers to applications and other libraries using the library.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="state-management"><a class="anchor" href="#state-management"></a>State Management</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="global-state"><a class="anchor" href="#global-state"></a>Global State</h3>
|
|
<div class="paragraph">
|
|
<p>Global state should be avoided.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If this is impossible, the global state must be protected with
|
|
a lock. For C/C++, you can use the
|
|
<code>pthread_mutex_lock</code>
|
|
and <code>pthread_mutex_unlock</code>
|
|
functions without linking against <code>-lpthread</code>
|
|
because the system provides stubs for non-threaded processes.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For compatibility with <code>fork</code>, these locks
|
|
should be acquired and released in helpers registered with
|
|
<code>pthread_atfork</code>. This function is not
|
|
available without <code>-lpthread</code>, so you need to
|
|
use <code>dlsym</code> or a weak symbol to obtain its
|
|
address.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you need <code>fork</code> protection for other
|
|
reasons, you should store the process ID and compare it to the
|
|
value returned by <code>getpid</code> each time you
|
|
access the global state. (<code>getpid</code> is not
|
|
implemented as a system call and is fast.) If the value
|
|
changes, you know that you have to re-create the state object.
|
|
(This needs to be combined with locking, of course.)</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="handles"><a class="anchor" href="#handles"></a>Handles</h3>
|
|
<div class="paragraph">
|
|
<p>Library state should be kept behind a curtain. Client code
|
|
should receive only a handle. In C, the handle can be a
|
|
pointer to an incomplete <code>struct</code>. In C++,
|
|
the handle can be a pointer to an abstract base class, or it
|
|
can be hidden using the pointer-to-implementation idiom.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The library should provide functions for creating and
|
|
destroying handles. (In C++, it is possible to use virtual
|
|
destructors for the latter.) Consistency between creation and
|
|
destruction of handles is strongly recommended: If the client
|
|
code created a handle, it is the responsibility of the client
|
|
code to destroy it. (This is not always possible or
|
|
convenient, so sometimes, a transfer of ownership has to
|
|
happen.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Using handles ensures that it is possible to change the way
|
|
the library represents state in a way that is transparent to
|
|
client code. This is important to facilitate security updates
|
|
and many other code changes.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is not always necessary to protect state behind a handle
|
|
with a lock. This depends on the level of thread safety
|
|
the library provides.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="object-orientation"><a class="anchor" href="#object-orientation"></a>Object Orientation</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Classes should be either designed as base classes, or it should
|
|
be impossible to use them as base classes (like
|
|
<code>final</code> classes in Java). Classes which are
|
|
not designed for inheritance and are used as base classes
|
|
nevertheless create potential maintenance hazards because it is
|
|
difficult to predict how client code will react when calls to
|
|
virtual methods are added, reordered or removed.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Virtual member functions can be used as callbacks. See
|
|
<a href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks">Callbacks</a>
|
|
for some of the challenges involved.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="sect-Defensive_Coding-Tasks-Library_Design-Callbacks"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks"></a>Callbacks</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Higher-order code is difficult to analyze for humans and
|
|
computers alike, so it should be avoided. Often, an
|
|
iterator-based interface (a library function which is called
|
|
repeatedly by client code and returns a stream of events) leads
|
|
to a better design which is easier to document and use.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If callbacks are unavoidable, some guidelines for them follow.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In modern C++ code, <code>std::function</code> objects
|
|
should be used for callbacks.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In older C++ code and in C code, all callbacks must have an
|
|
additional closure parameter of type <code>void *</code>,
|
|
the value of which can be specified by client code. If
|
|
possible, the value of the closure parameter should be provided
|
|
by client code at the same time a specific callback is
|
|
registered (or specified as a function argument). If a single
|
|
closure parameter is shared by multiple callbacks, flexibility
|
|
is greatly reduced, and conflicts between different pieces of
|
|
client code using the same library object could be unresolvable.
|
|
In some cases, it makes sense to provide a de-registration
|
|
callback which can be used to destroy the closure parameter when
|
|
the callback is no longer used.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Callbacks can throw exceptions or call
|
|
<code>longjmp</code>. If possible, all library objects
|
|
should remain in a valid state. (All further operations on them
|
|
can fail, but it should be possible to deallocate them without
|
|
causing resource leaks.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The presence of callbacks raises the question if functions
|
|
provided by the library are <strong>reentrant</strong>.
|
|
Unless a library was designed for such use, bad things will
|
|
happen if a callback function uses functions in the same library
|
|
(particularly if they are invoked on the same objects and
|
|
manipulate the same state). When the callback is invoked, the
|
|
library can be in an inconsistent state. Reentrant functions
|
|
are more difficult to write than thread-safe functions (by
|
|
definition, simple locking would immediately lead to deadlocks).
|
|
It is also difficult to decide what to do when destruction of an
|
|
object which is currently processing a callback is requested.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="process-attributes"><a class="anchor" href="#process-attributes"></a>Process Attributes</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Several attributes are global and affect all code in the
|
|
process, not just the library that manipulates them.</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>environment variables
|
|
(see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">[sect-Defensive_Coding-Tasks-secure_getenv]</a>)</p>
|
|
</li>
|
|
<li>
|
|
<p>umask</p>
|
|
</li>
|
|
<li>
|
|
<p>user IDs, group IDs and capabilities</p>
|
|
</li>
|
|
<li>
|
|
<p>current working directory</p>
|
|
</li>
|
|
<li>
|
|
<p>signal handlers, signal masks and signal delivery</p>
|
|
</li>
|
|
<li>
|
|
<p>file locks (especially <code>fcntl</code> locks
|
|
behave in surprising ways, not just in a multi-threaded
|
|
environment)</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Library code should avoid manipulating these global process
|
|
attributes. It should not rely on environment variables, umask,
|
|
the current working directory and signal masks because these
|
|
attributes can be inherited from an untrusted source.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In addition, there are obvious process-wide aspects such as the
|
|
virtual memory layout, the set of open files and dynamic shared
|
|
objects, but with the exception of shared objects, these can be
|
|
manipulated in a relatively isolated way.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="bottom" class="text-muted py-3" >
|
|
<div class="foot">
|
|
<div class="container">
|
|
<div class="row footerlinks">
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">About</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
|
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
|
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
|
</dl>
|
|
<ul class="list-inline">
|
|
<li>
|
|
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
|
</li>
|
|
<li>
|
|
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
|
</li>
|
|
<li>
|
|
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title uppercase">Download</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
|
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
|
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
|
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
|
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
|
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
|
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
|
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">Support</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
|
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
|
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
|
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">Join</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
|
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
|
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
|
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div> <!-- /row of widgets -->
|
|
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
<div class="widget-body">
|
|
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-7">
|
|
<div class="widget-body">
|
|
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
|
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
|
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
|
</div>
|
|
</div>
|
|
</div> <!-- /row of widgets -->
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
|
<!-- Latest compiled and minified JavaScript -->
|
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
|
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
|
<script type="text/javascript">
|
|
/*<![CDATA[*/
|
|
$(document).ready(function() {
|
|
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
|
}
|
|
});
|
|
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
|
}
|
|
});
|
|
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
|
});
|
|
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
|
});
|
|
});
|
|
/*]]>*/
|
|
</script>
|
|
</body>
|
|
</html> |