[defensive-coding-guide] 34/120: Descriptors: Note explicitly that
replacing select is the recommended approach
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 1207f12b39206cd3b5f2f1181c5fdcda2b265d3c
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Wed Aug 7 13:40:34 2013 +0200
Descriptors: Note explicitly that replacing select is the recommended approach
---
defensive-coding/en-US/Tasks/Descriptors.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/defensive-coding/en-US/Tasks/Descriptors.xml b/defensive-coding/en-US/Tasks/Descriptors.xml
index bdf1fb2..7b92ab9 100644
--- a/defensive-coding/en-US/Tasks/Descriptors.xml
+++ b/defensive-coding/en-US/Tasks/Descriptors.xml
@@ -217,7 +217,8 @@
be changed. <!-- ??? refer to event-driven programming -->
Calls to <function>select</function> can be replaced with
calls to <function>poll</function> or another event handling
- mechanism.
+ mechanism. Replacing the <function>select</function> function
+ is the recommended approach.
</para>
<para>
Alternatively, the library with high descriptor usage can
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 33/120: Title page: Reference the correct
logo file
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit f8d9c27c99a1095e6f5d6c81e5f1c9068f13ee77
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Mon Jul 22 10:17:28 2013 +0200
Title page: Reference the correct logo file
Fix suggested by Darrin Mison.
---
defensive-coding/en-US/Book_Info.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defensive-coding/en-US/Book_Info.xml b/defensive-coding/en-US/Book_Info.xml
index e3ec3ea..e7161b0 100644
--- a/defensive-coding/en-US/Book_Info.xml
+++ b/defensive-coding/en-US/Book_Info.xml
@@ -19,7 +19,7 @@
<corpauthor>
<inlinemediaobject>
<imageobject>
- <imagedata fileref="Common_Content/images/logo.svg" format="SVG" />
+ <imagedata fileref="Common_Content/images/title_logo.svg" format="SVG" />
</imageobject>
</inlinemediaobject>
</corpauthor>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 32/120: C allocators: Add cross-reference
to C integer arithmetic
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit bacb215c25d5f517fa4ffc9ddee4c00d7919f25b
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Wed Jul 10 14:24:15 2013 +0200
C allocators: Add cross-reference to C integer arithmetic
---
defensive-coding/en-US/C/Allocators.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/defensive-coding/en-US/C/Allocators.xml b/defensive-coding/en-US/C/Allocators.xml
index 974b6c1..e86b37f 100644
--- a/defensive-coding/en-US/C/Allocators.xml
+++ b/defensive-coding/en-US/C/Allocators.xml
@@ -135,7 +135,8 @@
is used, the size check must be written manually. For instance,
to allocate an array of <literal>n</literal> elements of type
<literal>T</literal>, check that the requested size is not
- greater than <literal>n / sizeof(T)</literal>.
+ greater than <literal>n / sizeof(T)</literal>. See <xref
+ linkend="sect-Defensive_Coding-C-Arithmetic"/>.
</para>
</section>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 31/120: Java: Add note on reading arrays
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 8512082515dfdd71a3a45627d4dd3b61fa84290b
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Fri Jul 5 11:07:13 2013 +0200
Java: Add note on reading arrays
---
defensive-coding/en-US/Java/Language.xml | 33 +++++++++++++
.../en-US/Java/snippets/Language-ReadArray.xml | 39 +++++++++++++++
defensive-coding/src/JavaReadArray.java | 55 ++++++++++++++++++++++
defensive-coding/src/src.mk | 1 +
4 files changed, 128 insertions(+)
diff --git a/defensive-coding/en-US/Java/Language.xml b/defensive-coding/en-US/Java/Language.xml
index edea9a4..e47df99 100644
--- a/defensive-coding/en-US/Java/Language.xml
+++ b/defensive-coding/en-US/Java/Language.xml
@@ -11,6 +11,34 @@
<xref linkend="sect-Defensive_Coding-Java-LowLevel"/>.
</para>
+ <section id="sect-Defensive_Coding-Java-Language-ReadArray">
+ <title>Inceasing robustness when reading arrays</title>
+ <para>
+ External data formats often include arrays, and the data is
+ stored as an integer indicating the number of array elements,
+ followed by this number of elements in the file or protocol data
+ unit. This length specified can be much larger than what is
+ actually available in the data source.
+ </para>
+ <para>
+ To avoid allocating extremely large amounts of data, you can
+ allocate a small array initially and grow it as you read more
+ data, implementing an exponential growth policy. See the
+ <function>readBytes(InputStream, int)</function> function in
+ <xref linkend="ex-Defensive_Coding-Java-Language-ReadArray"/>.
+ </para>
+ <example id="ex-Defensive_Coding-Java-Language-ReadArray">
+ <title>Incrementally reading a byte array</title>
+ <xi:include href="snippets/Language-ReadArray.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ When reading data into arrays, hash maps or hash sets, use the
+ default constructor and do not specify a size hint. You can
+ simply add the elements to the collection as you read them.
+ </para>
+ </section>
+
<section id="sect-Defensive_Coding-Java-Language-Resources">
<title>Resource management</title>
<para>
@@ -234,6 +262,11 @@
greater problems.
</para>
<para>
+ Code should be written in a way that avoids triggering errors.
+ See <xref linkend="sect-Defensive_Coding-Java-Language-ReadArray"/>
+ for an example.
+ </para>
+ <para>
It is usually necessary to log errors. Otherwise, no trace of
the problem might be left anywhere, making it very difficult
to diagnose realted failures. Consequently, if you catch
diff --git a/defensive-coding/en-US/Java/snippets/Language-ReadArray.xml b/defensive-coding/en-US/Java/snippets/Language-ReadArray.xml
new file mode 100644
index 0000000..1470795
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/Language-ReadArray.xml
@@ -0,0 +1,39 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+static byte[] readBytes(InputStream in, int length) throws IOException {
+ final int startSize = 65536;
+ byte[] b = new byte[Math.min(length, startSize)];
+ int filled = 0;
+ while (true) {
+ int remaining = b.length - filled;
+ readFully(in, b, filled, remaining);
+ if (b.length == length) {
+ break;
+ }
+ filled = b.length;
+ if (length - b.length <= b.length) {
+ // Allocate final length. Condition avoids overflow.
+ b = Arrays.copyOf(b, length);
+ } else {
+ b = Arrays.copyOf(b, b.length * 2);
+ }
+ }
+ return b;
+}
+
+static void readFully(InputStream in,byte[] b, int off, int len)
+ throws IOException {
+ int startlen = len;
+ while (len > 0) {
+ int count = in.read(b, off, len);
+ if (count < 0) {
+ throw new EOFException();
+ }
+ off += count;
+ len -= count;
+ }
+}
+</programlisting>
diff --git a/defensive-coding/src/JavaReadArray.java b/defensive-coding/src/JavaReadArray.java
new file mode 100644
index 0000000..06cba15
--- /dev/null
+++ b/defensive-coding/src/JavaReadArray.java
@@ -0,0 +1,55 @@
+import java.io.EOFException;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.util.Arrays;
+
+public class JavaReadArray {
+ public static void main(String[] args) throws IOException {
+ String path = args[0];
+ int length = Integer.parseInt(args[1]);
+
+ byte[] data;
+ try (InputStream in = new FileInputStream(path)) {
+ data = readBytes(in, length);
+ }
+ System.out.write(data);
+ }
+
+ //+ Java Language-ReadArray
+ static byte[] readBytes(InputStream in, int length) throws IOException {
+ final int startSize = 65536;
+ byte[] b = new byte[Math.min(length, startSize)];
+ int filled = 0;
+ while (true) {
+ int remaining = b.length - filled;
+ readFully(in, b, filled, remaining);
+ if (b.length == length) {
+ break;
+ }
+ filled = b.length;
+ if (length - b.length <= b.length) {
+ // Allocate final length. Condition avoids overflow.
+ b = Arrays.copyOf(b, length);
+ } else {
+ b = Arrays.copyOf(b, b.length * 2);
+ }
+ }
+ return b;
+ }
+
+ static void readFully(InputStream in,byte[] b, int off, int len)
+ throws IOException {
+ int startlen = len;
+ while (len > 0) {
+ int count = in.read(b, off, len);
+ if (count < 0) {
+ throw new EOFException();
+ }
+ off += count;
+ len -= count;
+ }
+ }
+ //-
+}
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index c916d01..219e70b 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -19,6 +19,7 @@ CFLAGS_Java-JNI-Pointers = \
# List Java files which sould be compiled
compile_java += JavaFinally
+compile_java += JavaReadArray
compile_java += JavaSecurityManagerUnprivileged
compile_java += JavaSecurityManagerPrivileged
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 30/120: Java: Add notes about the security
manager
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit b871c9eec0b2de9e50bab03d44776487e4abbcff
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Thu Jul 4 18:51:45 2013 +0200
Java: Add notes about the security manager
---
defensive-coding/en-US/Java/Java.xml | 1 +
defensive-coding/en-US/Java/SecurityManager.xml | 292 +++++++++++++++++++++
.../Java/snippets/SecurityManager-Callback.xml | 40 +++
.../snippets/SecurityManager-CurrentDirectory.xml | 8 +
.../Java/snippets/SecurityManager-Privileged.xml | 19 ++
.../Java/snippets/SecurityManager-Unprivileged.xml | 28 ++
.../src/JavaSecurityManagerPrivileged.java | 80 ++++++
.../src/JavaSecurityManagerUnprivileged.java | 80 ++++++
defensive-coding/src/data/java/grant-all.policy | 5 +
defensive-coding/src/src.mk | 2 +
10 files changed, 555 insertions(+)
diff --git a/defensive-coding/en-US/Java/Java.xml b/defensive-coding/en-US/Java/Java.xml
index 7c5700c..d7bf3ef 100644
--- a/defensive-coding/en-US/Java/Java.xml
+++ b/defensive-coding/en-US/Java/Java.xml
@@ -6,5 +6,6 @@
<xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="LowLevel.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="SecurityManager.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</chapter>
diff --git a/defensive-coding/en-US/Java/SecurityManager.xml b/defensive-coding/en-US/Java/SecurityManager.xml
new file mode 100644
index 0000000..2e18ac7
--- /dev/null
+++ b/defensive-coding/en-US/Java/SecurityManager.xml
@@ -0,0 +1,292 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<section id="sect-Defensive_Coding-Java-SecurityManager">
+ <title>Interacting with the security manager</title>
+ <para>
+ The Java platform is largely implemented in the Java language
+ itself. Therefore, within the same JVM, code runs which is part
+ of the Java installation and which is trusted, but there might
+ also be code which comes from untrusted sources and is restricted
+ by the Java sandbox (to varying degrees). The <emphasis>security
+ manager</emphasis> draws a line between fully trusted, partially
+ trusted and untrusted code.
+ </para>
+ <para>
+ The type safety and accessibility checks provided by the Java
+ language and JVM would be sufficient to implement a sandbox.
+ However, only some Java APIs employ such a capabilities-based
+ approach. (The Java SE library contains many public classes with
+ public constructors which can break any security policy, such as
+ <literal>java.io.FileOutputStream</literal>.) Instead, critical
+ functionality is protected by <emphasis>stack
+ inspection</emphasis>: At a security check, the stack is walked
+ from top (most-nested) to bottom. The security check fails if a
+ stack frame for a method is encountered whose class lacks the
+ permission which the security check requires.
+ </para>
+ <para>
+ This simple approach would not allow untrusted code (which lacks
+ certain permissions) to call into trusted code while the latter
+ retains trust. Such trust transitions are desirable because they
+ enable Java as an implementation language for most parts of the
+ Java platform, including security-relevant code. Therefore, there
+ is a mechanism to mark certain stack frames as trusted (<xref
+ linkend="sect-Defensive_Coding-Java-SecurityManager-Privileged"/>).
+ </para>
+ <para>
+ In theory, it is possible to run a Java virtual machine with a
+ security manager that acts very differently from this approach,
+ but a lot of code expects behavior very close to the platform
+ default (including many classes which are part of the OpenJDK
+ implementation).
+ </para>
+
+ <section id="sect-Defensive_Coding-Java-SecurityManager-Compatible">
+ <title>Security manager compatibility</title>
+ <para>
+ A lot of code can run without any additional permissions at all,
+ with little changes. The following guidelines should help to
+ increase compatibility with a restrictive security manager.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ When retrieving system properties using
+ <function>System.getProperty(String)</function> or similar
+ methods, catch <literal>SecurityException</literal>
+ exceptions and treat the property as unset.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Avoid unnecessary file system or network access.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Avoid explicit class loading. Access to a suitable class
+ loader might not be available when executing as untrusted
+ code.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ If the functionality you are implementing absolutely requires
+ privileged access and this functionality has to be used from
+ untrusted code (hopefully in a restricted and secure manner),
+ see <xref
+ linkend="sect-Defensive_Coding-Java-SecurityManager-Privileged"/>.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-SecurityManager-Activate">
+ <title>Activating the security manager</title>
+ <para>
+ The usual command to launch a Java application,
+ <command>java</command>, does not activate the security manager.
+ Therefore, the virtual machine does not enforce any sandboxing
+ restrictions, even if explicitly requested by the code (for
+ example, as described in <xref
+ linkend="sect-Defensive_Coding-Java-SecurityManager-Unprivileged"/>).
+ </para>
+ <para>
+ The <option>-Djava.security.manager</option> option activates
+ the security manager, with the fairly restrictive default
+ policy. With a very permissive policy, most Java code will run
+ unchanged. Assuming the policy in <xref
+ linkend="ex-Defensive_Coding-Java-SecurityManager-GrantAll"/>
+ has been saved in a file <filename>grant-all.policy</filename>,
+ this policy can be activated using the option
+ <option>-Djava.security.policy=grant-all.policy</option> (in
+ addition to the <option>-Djava.security.manager</option>
+ option).
+ </para>
+ <example id="ex-Defensive_Coding-Java-SecurityManager-GrantAll">
+ <title>Most permissve OpenJDK policy file</title>
+<programlisting>
+grant {
+ permission java.security.AllPermission;
+};
+</programlisting>
+ </example>
+ <para>
+ With this most permissive policy, the security manager is still
+ active, and explicit requests to drop privileges will be
+ honored.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-SecurityManager-Unprivileged">
+ <title>Reducing trust in code</title>
+ <para>
+ <xref linkend="ex-Defensive_Coding-Java-SecurityManager-Unprivileged"/>
+ shows how to run a piece code of with reduced privileges.
+ </para>
+ <example id="ex-Defensive_Coding-Java-SecurityManager-Unprivileged">
+ <title>Using the security manager to run code with reduced
+ privileges</title>
+ <xi:include href="snippets/SecurityManager-Unprivileged.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ The example above does not add any additional permissions to the
+ <literal>permissions</literal> object. If such permissions are
+ necessary, code like the following (which grants read permission
+ on all files in the current directory) can be used:
+ </para>
+ <informalexample>
+ <xi:include href="snippets/SecurityManager-CurrentDirectory.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </informalexample>
+ <important>
+ <para>
+ Calls to the
+ <function>java.security.AccessController.doPrivileged()</function>
+ methods do not enforce any additional restriction if no
+ security manager has been set. Except for a few special
+ exceptions, the restrictions no longer apply if the
+ <function>doPrivileged()</function> has returned, even to
+ objects created by the code which ran with reduced privileges.
+ (This applies to object finalization in particular.)
+ </para>
+ <para>
+ The example code above does not prevent the called code from
+ calling the
+ <function>java.security.AccessController.doPrivileged()</function>
+ methods. This mechanism should be considered an additional
+ safety net, but it still can be used to prevent unexpected
+ behavior of trusted code. As long as the executed code is not
+ dynamic and came with the original application or library, the
+ sandbox is fairly effective.
+ </para>
+ <para>
+ The <literal>context</literal> argument in <xref
+ linkend="ex-Defensive_Coding-Java-SecurityManager-Unprivileged"/>
+ is extremely important—otherwise, this code would increase
+ privileges instead of reducing them.
+ </para>
+ </important>
+ <para>
+ For activating the security manager, see <xref
+ linkend="sect-Defensive_Coding-Java-SecurityManager-Activate"/>.
+ Unfortunately, this affects the virtual machine as a whole, so
+ it is not possible to do this from a library.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-SecurityManager-Privileged">
+ <title>Re-gaining privileges</title>
+ <para>
+ Ordinarily, when trusted code is called from untrusted code, it
+ loses its privileges (because of the untrusted stack frames
+ visible to stack inspection). The
+ <function>java.security.AccessController.doPrivileged()</function>
+ family of methods provides a controlled backdoor from untrusted
+ to trusted code.
+ </para>
+ <important>
+ <para>
+ By design, this feature can undermine the Java security model
+ and the sandbox. It has to be used very carefully. Most
+ sandbox vulnerabilities can be traced back to its misuse.
+ </para>
+ </important>
+ <para>
+ In essence, the <function>doPrivileged()</function> methods
+ cause the stack inspection to end at their call site. Untrusted
+ code further down the call stack becomes invisible to security
+ checks.
+ </para>
+ <para>
+ The following operations are common and safe to perform with
+ elevated privileges.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Reading custom system properties with fixed names,
+ especially if the value is not propagated to untrusted code.
+ (File system paths including installation paths, host names
+ and user names are sometimes considered private information
+ and need to be protected.)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Reading from the file system at fixed paths, either
+ determined at compile time or by a system property. Again,
+ leaking the file contents to the caller can be problematic.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Accessing network resources under a fixed address, name or
+ URL, derived from a system property or configuration file,
+ information leaks not withstanding.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <xref linkend="ex-Defensive_Coding-Java-SecurityManager-Privileged"/>
+ shows how to request additional privileges.
+ </para>
+ <example id="ex-Defensive_Coding-Java-SecurityManager-Privileged">
+ <title>Using the security manager to run code with increased
+ privileges</title>
+ <xi:include href="snippets/SecurityManager-Privileged.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ Obviously, this only works if the class containing the call to
+ <function>doPrivileged()</function> is marked trusted (usually
+ because it is loaded from a trusted class loader).
+ </para>
+ <para>
+ When writing code that runs with elevated privileges, make sure
+ that you follow the rules below.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Make the privileged code as small as possible. Perform as
+ many computations as possible before and after the
+ privileged code section, even if it means that you have to
+ define a new class to pass the data around.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make sure that you either control the inputs to the
+ privileged code, or that the inputs are harmless and cannot
+ affect security properties of the privileged code.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Data that is returned from or written by the privileged code
+ must either be restricted (that is, it cannot be accessed by
+ untrusted code), or must be harmless. Otherwise, privacy
+ leaks or information disclosures which affect security
+ properties can be the result.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ If the code calls back into untrusted code at a later stage (or
+ performs other actions under control from the untrusted caller),
+ you must obtain the original security context and restore it
+ before performing the callback, as in <xref
+ linkend="ex-Defensive_Coding-Java-SecurityManager-Callback"/>.
+ (In this example, it would be much better to move the callback
+ invocation out of the privileged code section, of course.)
+ </para>
+ <example id="ex-Defensive_Coding-Java-SecurityManager-Callback">
+ <title>Restoring privileges when invoking callbacks</title>
+ <xi:include href="snippets/SecurityManager-Callback.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ </section>
+
+</section>
+
diff --git a/defensive-coding/en-US/Java/snippets/SecurityManager-Callback.xml b/defensive-coding/en-US/Java/snippets/SecurityManager-Callback.xml
new file mode 100644
index 0000000..634d62f
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/SecurityManager-Callback.xml
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+interface Callback<T> {
+ T call(boolean flag);
+}
+
+class CallbackInvoker<T> {
+ private final AccessControlContext context;
+ Callback<T> callback;
+
+ CallbackInvoker(Callback<T> callback) {
+ context = AccessController.getContext();
+ this.callback = callback;
+ }
+
+ public T invoke() {
+ // Obtain increased privileges.
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ @Override
+ public T run() {
+ // This operation would fail without
+ // additional privileges.
+ final boolean flag = Boolean.getBoolean("some.property");
+
+ // Restore the original privileges.
+ return AccessController.doPrivileged(
+ new PrivilegedAction<T>() {
+ @Override
+ public T run() {
+ return callback.call(flag);
+ }
+ }, context);
+ }
+ });
+ }
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/SecurityManager-CurrentDirectory.xml b/defensive-coding/en-US/Java/snippets/SecurityManager-CurrentDirectory.xml
new file mode 100644
index 0000000..1a4d022
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/SecurityManager-CurrentDirectory.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+permissions.add(new FilePermission(
+ System.getProperty("user.dir") + "/-", "read"));
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/SecurityManager-Privileged.xml b/defensive-coding/en-US/Java/snippets/SecurityManager-Privileged.xml
new file mode 100644
index 0000000..b700a0e
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/SecurityManager-Privileged.xml
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+// This is expected to fail.
+try {
+ System.out.println(System.getProperty("user.home"));
+} catch (SecurityException e) {
+ e.printStackTrace(System.err);
+}
+AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ // This should work.
+ System.out.println(System.getProperty("user.home"));
+ return null;
+ }
+ });
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/SecurityManager-Unprivileged.xml b/defensive-coding/en-US/Java/snippets/SecurityManager-Unprivileged.xml
new file mode 100644
index 0000000..29bb4f5
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/SecurityManager-Unprivileged.xml
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+Permissions permissions = new Permissions();
+ ProtectionDomain protectionDomain =
+ new ProtectionDomain(null, permissions);
+ AccessControlContext context = new AccessControlContext(
+ new ProtectionDomain[] { protectionDomain });
+
+// This is expected to succeed.
+try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+}
+
+AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ // This code runs with reduced privileges and is
+ // expected to fail.
+ try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+ }
+ return null;
+ }
+ }, context);
+</programlisting>
diff --git a/defensive-coding/src/JavaSecurityManagerPrivileged.java b/defensive-coding/src/JavaSecurityManagerPrivileged.java
new file mode 100644
index 0000000..46da7a0
--- /dev/null
+++ b/defensive-coding/src/JavaSecurityManagerPrivileged.java
@@ -0,0 +1,80 @@
+// Test with:
+//
+// java -Djava.security.manager \
+// JavaSecurityManagerPrivileged
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+public class JavaSecurityManagerPrivileged {
+ public static void main(String[] args) throws Exception {
+ Permissions permissions = new Permissions();
+ ProtectionDomain protectionDomain =
+ new ProtectionDomain(null, permissions);
+ AccessControlContext context = new AccessControlContext(
+ new ProtectionDomain[] { protectionDomain });
+
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ //+ Java SecurityManager-Privileged
+ // This is expected to fail.
+ try {
+ System.out.println(System.getProperty("user.home"));
+ } catch (SecurityException e) {
+ e.printStackTrace(System.err);
+ }
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ // This should work.
+ System.out.println(System.getProperty("user.home"));
+ return null;
+ }
+ });
+ //-
+ return null;
+ }
+ }, context);
+
+ }
+
+ //+ Java SecurityManager-Callback
+ interface Callback<T> {
+ T call(boolean flag);
+ }
+
+ class CallbackInvoker<T> {
+ private final AccessControlContext context;
+ Callback<T> callback;
+
+ CallbackInvoker(Callback<T> callback) {
+ context = AccessController.getContext();
+ this.callback = callback;
+ }
+
+ public T invoke() {
+ // Obtain increased privileges.
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ @Override
+ public T run() {
+ // This operation would fail without
+ // additional privileges.
+ final boolean flag = Boolean.getBoolean("some.property");
+
+ // Restore the original privileges.
+ return AccessController.doPrivileged(
+ new PrivilegedAction<T>() {
+ @Override
+ public T run() {
+ return callback.call(flag);
+ }
+ }, context);
+ }
+ });
+ }
+ }
+ //-
+}
diff --git a/defensive-coding/src/JavaSecurityManagerUnprivileged.java b/defensive-coding/src/JavaSecurityManagerUnprivileged.java
new file mode 100644
index 0000000..61da297
--- /dev/null
+++ b/defensive-coding/src/JavaSecurityManagerUnprivileged.java
@@ -0,0 +1,80 @@
+// Test with:
+//
+// java -Djava.security.manager \
+// -Djava.security.policy=data/java/grant-all.policy \
+// JavaSecurityManagerUnprivileged JavaFinally.java {true|false}
+
+import java.io.FileInputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+
+public class JavaSecurityManagerUnprivileged {
+ public static void main(String[] args) throws Exception {
+ final String path = args[0];
+ boolean grant = Boolean.parseBoolean(args[1]);
+ if (grant) {
+ withGrant(path);
+ return;
+ }
+
+ //+ Java SecurityManager-Unprivileged
+ Permissions permissions = new Permissions();
+ ProtectionDomain protectionDomain =
+ new ProtectionDomain(null, permissions);
+ AccessControlContext context = new AccessControlContext(
+ new ProtectionDomain[] { protectionDomain });
+
+ // This is expected to succeed.
+ try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+ }
+
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ // This code runs with reduced privileges and is
+ // expected to fail.
+ try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+ }
+ return null;
+ }
+ }, context);
+ //-
+ }
+
+ private static void withGrant(String path) throws Exception {
+ Permissions permissions = new Permissions();
+ //+ Java SecurityManager-CurrentDirectory
+ permissions.add(new FilePermission(
+ System.getProperty("user.dir") + "/-", "read"));
+ //-
+ ProtectionDomain protectionDomain =
+ new ProtectionDomain(null, permissions);
+ AccessControlContext context = new AccessControlContext(
+ new ProtectionDomain[] { protectionDomain });
+
+ // This is expected to succeed.
+ try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+ }
+
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ // This code runs with reduced privileges and is
+ // expected to fail.
+ try (FileInputStream in = new FileInputStream(path)) {
+ System.out.format("FileInputStream: %s%n", in);
+ return null;
+ }
+ }
+ }, context);
+ }
+}
diff --git a/defensive-coding/src/data/java/grant-all.policy b/defensive-coding/src/data/java/grant-all.policy
new file mode 100644
index 0000000..ce74daa
--- /dev/null
+++ b/defensive-coding/src/data/java/grant-all.policy
@@ -0,0 +1,5 @@
+// Used by the JavaSecurityManagerUnprivileged example.
+
+grant {
+ permission java.security.AllPermission;
+};
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index 1bd5f45..c916d01 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -19,6 +19,8 @@ CFLAGS_Java-JNI-Pointers = \
# List Java files which sould be compiled
compile_java += JavaFinally
+compile_java += JavaSecurityManagerUnprivileged
+compile_java += JavaSecurityManagerPrivileged
compile_java += TLSClientOpenJDK
JCFLAGS_TLSClientOpenJDK = -source 1.6 -target 1.6
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 29/120: Add a chapter on Java
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 458170e75967373354e76f97dcfed1d974605e4e
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Tue Jul 2 17:43:24 2013 +0200
Add a chapter on Java
---
defensive-coding/en-US/Defensive_Coding.xml | 1 +
defensive-coding/en-US/Java/Java.xml | 10 +
defensive-coding/en-US/Java/Language.xml | 258 +++++++++++++++++++++
defensive-coding/en-US/Java/LowLevel.xml | 157 +++++++++++++
defensive-coding/en-US/Java/schemas.xml | 5 +
defensive-coding/en-US/Java/snippets/Finally.xml | 12 +
.../en-US/Java/snippets/JNI-Pointers.xml | 36 +++
.../en-US/Java/snippets/TryWithResource.xml | 9 +
defensive-coding/src/Java-JNI-Pointers.c | 41 ++++
defensive-coding/src/JavaFinally.java | 31 +++
defensive-coding/src/src.mk | 9 +-
11 files changed, 568 insertions(+), 1 deletion(-)
diff --git a/defensive-coding/en-US/Defensive_Coding.xml b/defensive-coding/en-US/Defensive_Coding.xml
index cef4bbf..eb6e763 100644
--- a/defensive-coding/en-US/Defensive_Coding.xml
+++ b/defensive-coding/en-US/Defensive_Coding.xml
@@ -6,6 +6,7 @@
<title>Programming Languages</title>
<xi:include href="C/C.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="CXX/CXX.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Java/Java.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Python/Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part>
diff --git a/defensive-coding/en-US/Java/Java.xml b/defensive-coding/en-US/Java/Java.xml
new file mode 100644
index 0000000..7c5700c
--- /dev/null
+++ b/defensive-coding/en-US/Java/Java.xml
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<chapter id="chap-Defensive_Coding-Java">
+ <title>The Java Programming Language</title>
+
+ <xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="LowLevel.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+</chapter>
+
diff --git a/defensive-coding/en-US/Java/Language.xml b/defensive-coding/en-US/Java/Language.xml
new file mode 100644
index 0000000..edea9a4
--- /dev/null
+++ b/defensive-coding/en-US/Java/Language.xml
@@ -0,0 +1,258 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<section id="sect-Defensive_Coding-Java-Language">
+ <title>The core language</title>
+ <para>
+ Implementations of the Java programming language provide strong
+ memory safety, even in the presence of data races in concurrent
+ code. This prevents a large range of security vulnerabilities
+ from occurring, unless certain low-level features are used; see
+ <xref linkend="sect-Defensive_Coding-Java-LowLevel"/>.
+ </para>
+
+ <section id="sect-Defensive_Coding-Java-Language-Resources">
+ <title>Resource management</title>
+ <para>
+ Unlike C++, Java does not offer destructors which can deallocate
+ resources in a predictable fashion. All resource management has
+ to be manual, at the usage site. (Finalizers are generally not
+ usable for resource management, especially in high-performance
+ code; see <xref
+ linkend="sect-Defensive_Coding-Java-Language-Finalizers"/>.)
+ </para>
+ <para>
+ The first option is the
+ <literal>try</literal>-<literal>finally</literal> construct, as
+ shown in <xref linkend="ex-Defensive_Coding-Java-Language-Finally"/>.
+ The code in the <literal>finally</literal> block should be as short as
+ possible and should not throw any exceptions.
+ </para>
+ <example id="ex-Defensive_Coding-Java-Language-Finally">
+ <title>Resource management with a
+ <literal>try</literal>-<literal>finally</literal> block</title>
+ <xi:include href="snippets/Finally.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ Note that the resource allocation happens
+ <emphasis>outside</emphasis> the <literal>try</literal> block,
+ and that there is no <literal>null</literal> check in the
+ <literal>finally</literal> block. (Both are common artifacts
+ stemming from IDE code templates.)
+ </para>
+ <para>
+ If the resource object is created freshly and implements the
+ <literal>java.lang.AutoCloseable</literal> interface, the code
+ in <xref
+ linkend="ex-Defensive_Coding-Java-Language-TryWithResource"/> can be
+ used instead. The Java compiler will automatically insert the
+ <function>close()</function> method call in a synthetic
+ <literal>finally</literal> block.
+ </para>
+ <example id="ex-Defensive_Coding-Java-Language-TryWithResource">
+ <title>Resource management using the
+ <literal>try</literal>-with-resource construct</title>
+ <xi:include href="snippets/TryWithResource.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ To be compatible with the <literal>try</literal>-with-resource
+ construct, new classes should name the resource deallocation
+ method <function>close()</function>, and implement the
+ <literal>AutoCloseable</literal> interface (the latter breaking
+ backwards compatibility with Java 6). However, using the
+ <literal>try</literal>-with-resource construct with objects that
+ are not freshly allocated is at best awkward, and an explicit
+ <literal>finally</literal> block is usually the better approach.
+ </para>
+ <para>
+ In general, it is best to design the programming interface in
+ such a way that resource deallocation methods like
+ <function>close()</function> cannot throw any (checked or
+ unchecked) exceptions, but this should not be a reason to ignore
+ any actual error conditions.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-Language-Finalizers">
+ <title>Finalizers</title>
+ <para>
+ Finalizers can be used a last-resort approach to free resources
+ which would otherwise leak. Finalization is unpredictable,
+ costly, and there can be a considerable delay between the last
+ reference to an object going away and the execution of the
+ finalizer. Generally, manual resource management is required;
+ see <xref linkend="sect-Defensive_Coding-Java-Language-Resources"/>.
+ </para>
+ <para>
+ Finalizers should be very short and should only deallocate
+ native or other external resources held directly by the object
+ being finalized. In general, they must use synchronization:
+ Finalization necessarily happens on a separate thread because it is
+ inherently concurrent. There can be multiple finalization
+ threads, and despite each object being finalized at most once,
+ the finalizer must not assume that it has exclusive access to
+ the object being finalized (in the <literal>this</literal>
+ pointer).
+ </para>
+ <para>
+ Finalizers should not deallocate resources held by other
+ objects, especially if those objects have finalizers on their
+ own. In particular, it is a very bad idea to define a finalizer
+ just to invoke the resource deallocation method of another object,
+ or overwrite some pointer fields.
+ </para>
+ <para>
+ Finalizers are not guaranteed to run at all. For instance, the
+ virtual machine (or the machine underneath) might crash,
+ preventing their execution.
+ </para>
+ <para>
+ Objects with finalizers are garbage-collected much later than
+ objects without them, so using finalizers to zero out key
+ material (to reduce its undecrypted lifetime in memory) may have
+ the opposite effect, keeping objects around for much longer and
+ prevent them from being overwritten in the normal course of
+ program execution.
+ </para>
+ <para>
+ For the same reason, code which allocates objects with
+ finalizers at a high rate will eventually fail (likely with a
+ <literal>java.lang.OutOfMemoryError</literal> exception) because
+ the virtual machine has finite resources for keeping track of
+ objects pending finalization. To deal with that, it may be
+ necessary to recycle objects with finalizers.
+ </para>
+ <para>
+ The remarks in this section apply to finalizers which are
+ implemented by overriding the <function>finalize()</function>
+ method, and to custom finalization using reference queues.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-Language-Exceptions">
+ <title>Recovering from exceptions and errors</title>
+ <para>
+ Java exceptions come in three kinds, all ultimately deriving
+ from <literal>java.lang.Throwable</literal>:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Run-time exceptions</emphasis> do not have to be
+ declared explicitly and can be explicitly thrown from any
+ code, by calling code which throws them, or by triggering an
+ error condition at run time, like division by zero, or an
+ attempt at an out-of-bounds array access. These exceptions
+ derive from from the
+ <literal>java.lang.RuntimeException</literal> class (perhaps
+ indirectly).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Checked exceptions</emphasis> have to be declared
+ explicitly by functions that throw or propagate them. They
+ are similar to run-time exceptions in other regards, except
+ that there is no language construct to throw them (except
+ the <literal>throw</literal> statement itself). Checked
+ exceptions are only present at the Java language level and
+ are only enforced at compile time. At run time, the virtual
+ machine does not know about them and permits throwing
+ exceptions from any code. Checked exceptions must derive
+ (perhaps indirectly) from the
+ <literal>java.lang.Exception</literal> class, but not from
+ <literal>java.lang.RuntimeException</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Errors</emphasis> are exceptions which typically
+ reflect serious error conditions. They can be thrown at any
+ point in the program, and do not have to be declared (unlike
+ checked exceptions). In general, it is not possible to
+ recover from such errors; more on that below, in <xref
+ linkend="sect-Defensive_Coding-Java-Language-Exceptions-Errors"/>.
+ Error classes derive (perhaps indirectly) from
+ <literal>java.lang.Error</literal>, or from
+ <literal>java.lang.Throwable</literal>, but not from
+ <literal>java.lang.Exception</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The general expection is that run-time errors are avoided by
+ careful programming (e.g., not dividing by zero). Checked
+ exception are expected to be caught as they happen (e.g., when
+ an input file is unexpectedly missing). Errors are impossible
+ to predict and can happen at any point and reflect that
+ something went wrong beyond all expectations.
+ </para>
+
+ <section id="sect-Defensive_Coding-Java-Language-Exceptions-Errors">
+ <title>The difficulty of catching errors</title>
+ <para>
+ Errors (that is, exceptions which do not (indirectly) derive
+ from <literal>java.lang.Exception</literal>), have the
+ peculiar property that catching them is problematic. There
+ are several reasons for this:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The error reflects a failed consistenty check, for example,
+ <literal>java.lang.AssertionError</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The error can happen at any point, resulting in
+ inconsistencies due to half-updated objects. Examples are
+ <literal>java.lang.ThreadDeath</literal>,
+ <literal>java.lang.OutOfMemoryError</literal> and
+ <literal>java.lang.StackOverflowError</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The error indicates that virtual machine failed to provide
+ some semantic guarantees by the Java programming language.
+ <literal>java.lang.ExceptionInInitializerError</literal>
+ is an example—it can leave behind a half-initialized
+ class.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In general, if an error is thrown, the virtual machine should
+ be restarted as soon as possible because it is in an
+ inconsistent state. Continuing running as before can have
+ unexpected consequences. However, there are legitimate
+ reasons for catching errors because not doing so leads to even
+ greater problems.
+ </para>
+ <para>
+ It is usually necessary to log errors. Otherwise, no trace of
+ the problem might be left anywhere, making it very difficult
+ to diagnose realted failures. Consequently, if you catch
+ <literal>java.lang.Exception</literal> to log and suppress all
+ unexpected exceptions (for example, in a request dispatching
+ loop), you should consider switching to
+ <literal>java.lang.Throwable</literal> instead, to also cover
+ errors.
+ </para>
+ <para>
+ The other reason mainly applies to such request dispatching
+ loops: If you do not catch errors, the loop stops looping,
+ resulting in a denial of service.
+ </para>
+ <para>
+ However, if possible, catching errors should be coupled with a
+ way to signal the requirement of a virtual machine restart.
+ </para>
+ </section>
+ </section>
+</section>
+
diff --git a/defensive-coding/en-US/Java/LowLevel.xml b/defensive-coding/en-US/Java/LowLevel.xml
new file mode 100644
index 0000000..18ba1ad
--- /dev/null
+++ b/defensive-coding/en-US/Java/LowLevel.xml
@@ -0,0 +1,157 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<section id="sect-Defensive_Coding-Java-LowLevel">
+ <title>Low-level features of the virtual machine</title>
+
+ <section id="sect-Defensive_Coding-Java-Reflection">
+ <title><literal>Reflection and private parts</literal></title>
+ <para>
+ The <function>setAccessible(boolean)</function> method of the
+ <literal>java.lang.reflect.AccessibleObject</literal> class
+ allows a program to disable language-defined access rules for
+ specific constructors, methods, or fields. Once the access
+ checks are disabled, any code can use the
+ <literal>java.lang.reflect.Constructor</literal>,
+ <literal>java.lang.reflect.Method</literal>, or
+ <literal>java.lang.reflect.Field</literal> object to access the
+ underlying Java entity, without further permission checks. This
+ breaks encapsulation and can undermine the stability of the
+ virtual machine. (In contrast, without using the
+ <function>setAccessible(boolean)</function> method, this should
+ not happen because all the language-defined checks still apply.)
+ </para>
+ <para>
+ This feature should be avoided if possible.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-JNI">
+ <title>Java Native Interface (JNI)</title>
+ <para>
+ The Java Native Interface allows calling from Java code
+ functions specifically written for this purpose, usually in C or
+ C++.
+ </para>
+ <para>
+ The transition between the Java world and the C world is not
+ fully type-checked, and the C code can easily break the Java
+ virtual machine semantics. Therefore, extra care is needed when
+ using this functionality.
+ </para>
+ <para>
+ To provide a moderate amount of type safety, it is recommended
+ to recreate the class-specific header file using
+ <application>javah</application> during the build process,
+ include it in the implementation, and use the
+ <option>-Wmissing-declarations</option> option.
+ </para>
+ <para>
+ Ideally, the required data is directly passed to static JNI
+ methods and returned from them, and the code and the C side does
+ not have to deal with accessing Java fields (or even methods).
+ </para>
+ <para>
+ When using <function>GetPrimitiveArrayCritical</function> or
+ <function>GetStringCritical</function>, make sure that you only
+ perform very little processing between the get and release
+ operations. Do not access the file system or the network, and
+ not perform locking, because that might introduce blocking.
+ When processing large strings or arrays, consider splitting the
+ computation into multiple sub-chunks, so that you do not prevent
+ the JVM from reaching a safepoint for extended periods of time.
+ </para>
+ <para>
+ If necessary, you can use the Java <literal>long</literal> type
+ to store a C pointer in a field of a Java class. On the C side,
+ when casting between the <literal>jlong</literal> value and the
+ pointer on the C side,
+ </para>
+ <para>
+ You should not try to perform pointer arithmetic on the Java
+ side (that is, you should treat pointer-carrying
+ <literal>long</literal> values as opaque). When passing a slice
+ of an array to the native code, follow the Java convention and
+ pass it as the base array, the integer offset of the start of
+ the slice, and the integer length of the slice. On the native
+ side, check the offset/length combination against the actual
+ array length, and use the offset to compute the pointer to the
+ beginning of the array.
+ </para>
+ <example id="ex-Defensive_Coding-Java-JNI-Pointers">
+ <title>Array length checking in JNI code</title>
+ <xi:include href="snippets/JNI-Pointers.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ In any case, classes referring to native resources must be
+ declared <literal>final</literal>, and must not be serializeable
+ or cloneable. Initialization and mutation of the state used by
+ the native side must be controlled carefully. Otherwise, it
+ might be possible to create an object with inconsistent native
+ state which results in a crash (or worse) when used (or perhaps
+ only finalized) later. If you need both Java inheritance and
+ native resources, you should consider moving the native state to
+ a separate class, and only keep a reference to objects of that
+ class. This way, cloning and serialization issues can be
+ avoided in most cases.
+ </para>
+ <para>
+ If there are native resources associated with an object, the
+ class should have an explicit resource deallocation method
+ (<xref
+ linkend="sect-Defensive_Coding-Java-Language-Resources"/>) and a
+ finalizer (<xref
+ linkend="sect-Defensive_Coding-Java-Language-Finalizers"/>) as a
+ last resort. The need for finalization means that a minimum
+ amount of synchronization is needed. Code on the native side
+ should check that the object is not in a closed/freed state.
+ </para>
+ <para>
+ Many JNI functions create local references. By default, these
+ persist until the JNI-implemented method returns. If you create
+ many such references (e.g., in a loop), you may have to free
+ them using <function>DeleteLocalRef</function>, or start using
+ <function>PushLocalFrame</function> and
+ <function>PopLocalFrame</function>. Global references must be
+ deallocated with <function>DeleteGlobalRef</function>, otherwise
+ there will be a memory leak, just as with
+ <function>malloc</function> and <function>free</function>.
+ </para>
+ <para>
+ When throwing exceptions using <function>Throw</function> or
+ <function>ThrowNew</function>, be aware that these functions
+ return regularly. You have to return control manually to the
+ JVM.
+ </para>
+ <para>
+ Technically, the <literal>JNIEnv</literal> pointer is not
+ necessarily constant during the lifetime of your JNI module.
+ Storing it in a global variable is therefore incorrect.
+ Particularly if you are dealing with callbacks, you may have to
+ store the pointer in a thread-local variable (defined with
+ <literal>__thread</literal>). It is, however, best to avoid the
+ complexity of calling back into Java code.
+ </para>
+ <para>
+ Keep in mind that C/C++ and Java are different languages,
+ despite very similar syntax for expressions. The Java memory
+ model is much more strict than the C or C++ memory models, and
+ native code needs more synchronization, usually using JVM
+ facilities or POSIX threads mutexes. Integer overflow in Java
+ is defined, but in C/C++ it is not (for the
+ <literal>jint</literal> and <literal>jlong</literal> types).
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-MiscUnsafe">
+ <title><literal>sun.misc.Unsafe</literal></title>
+ <para>
+ The <literal>sun.misc.Unsafe</literal> class is unportable and
+ contains many functions explicitly designed to break Java memory
+ safety (for performance and debugging). If possible, avoid
+ using this class.
+ </para>
+ </section>
+
+</section>
diff --git a/defensive-coding/en-US/Java/schemas.xml b/defensive-coding/en-US/Java/schemas.xml
new file mode 100644
index 0000000..b18bd04
--- /dev/null
+++ b/defensive-coding/en-US/Java/schemas.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+ <uri resource="Language.xml" uri="../../docbook-schema/docbook.rnc"/>
+ <uri resource="LowLevel.xml" uri="../../docbook-schema/docbook.rnc"/>
+</locatingRules>
diff --git a/defensive-coding/en-US/Java/snippets/Finally.xml b/defensive-coding/en-US/Java/snippets/Finally.xml
new file mode 100644
index 0000000..b32ec36
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/Finally.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+InputStream in = new BufferedInputStream(new FileInputStream(path));
+try {
+ readFile(in);
+} finally {
+ in.close();
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml b/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml
new file mode 100644
index 0000000..95d386e
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *jEnv, jclass clazz, jbyteArray buffer, jint offset, jint length)
+{
+ assert(sizeof(jint) == sizeof(unsigned));
+ if (offset < 0 || length < 0) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "negative offset/length");
+ return 0;
+ }
+ unsigned uoffset = offset;
+ unsigned ulength = length;
+ // This cannot overflow because of the check above.
+ unsigned totallength = uoffset + ulength;
+ unsigned actuallength = (*jEnv)->GetArrayLength(jEnv, buffer);
+ if (totallength > actuallength) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "offset + length too large");
+ return 0;
+ }
+ unsigned char *ptr = (*jEnv)->GetPrimitiveArrayCritical(jEnv, buffer, 0);
+ if (ptr == NULL) {
+ return 0;
+ }
+ unsigned long long sum = 0;
+ for (unsigned char *p = ptr + uoffset, *end = p + ulength; p != end; ++p) {
+ sum += *p;
+ }
+ (*jEnv)->ReleasePrimitiveArrayCritical(jEnv, buffer, ptr, 0);
+ return sum;
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/TryWithResource.xml b/defensive-coding/en-US/Java/snippets/TryWithResource.xml
new file mode 100644
index 0000000..a9f13f6
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/TryWithResource.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
+ readFile(in);
+}
+</programlisting>
diff --git a/defensive-coding/src/Java-JNI-Pointers.c b/defensive-coding/src/Java-JNI-Pointers.c
new file mode 100644
index 0000000..c9108a6
--- /dev/null
+++ b/defensive-coding/src/Java-JNI-Pointers.c
@@ -0,0 +1,41 @@
+#include <jni.h>
+
+#include <assert.h>
+
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *, jclass, jbyteArray, jint, jint);
+
+static jclass arrayIndexOutOfBoundsExceptionClass;
+
+//+ Java JNI-Pointers
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *jEnv, jclass clazz, jbyteArray buffer, jint offset, jint length)
+{
+ assert(sizeof(jint) == sizeof(unsigned));
+ if (offset < 0 || length < 0) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "negative offset/length");
+ return 0;
+ }
+ unsigned uoffset = offset;
+ unsigned ulength = length;
+ // This cannot overflow because of the check above.
+ unsigned totallength = uoffset + ulength;
+ unsigned actuallength = (*jEnv)->GetArrayLength(jEnv, buffer);
+ if (totallength > actuallength) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "offset + length too large");
+ return 0;
+ }
+ unsigned char *ptr = (*jEnv)->GetPrimitiveArrayCritical(jEnv, buffer, 0);
+ if (ptr == NULL) {
+ return 0;
+ }
+ unsigned long long sum = 0;
+ for (unsigned char *p = ptr + uoffset, *end = p + ulength; p != end; ++p) {
+ sum += *p;
+ }
+ (*jEnv)->ReleasePrimitiveArrayCritical(jEnv, buffer, ptr, 0);
+ return sum;
+}
+//-
diff --git a/defensive-coding/src/JavaFinally.java b/defensive-coding/src/JavaFinally.java
new file mode 100644
index 0000000..7c0fe54
--- /dev/null
+++ b/defensive-coding/src/JavaFinally.java
@@ -0,0 +1,31 @@
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+public abstract class JavaFinally {
+ File path;
+
+ abstract void readFile(InputStream in) throws Exception;
+
+ void finallyExample() throws Exception {
+ //+ Java Finally
+ InputStream in = new BufferedInputStream(new FileInputStream(path));
+ try {
+ readFile(in);
+ } finally {
+ in.close();
+ }
+ //-
+ }
+
+ void tryWithResource() throws Exception {
+ //+ Java TryWithResource
+ try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
+ readFile(in);
+ }
+ //-
+ }
+
+ static native int sum(byte[] buffer, int offset, int length);
+}
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index f2eac6f..1bd5f45 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -13,8 +13,15 @@ compile_only += C-Pointers-remaining
compile_only += C-Arithmetic-add
compile_only += C-Arithmetic-mult
+compile_only += Java-JNI-Pointers
+CFLAGS_Java-JNI-Pointers = \
+ -I/usr/lib/jvm/java/include -I/usr/lib/jvm/java/include/linux
+
# List Java files which sould be compiled
+compile_java += JavaFinally
+
compile_java += TLSClientOpenJDK
+JCFLAGS_TLSClientOpenJDK = -source 1.6 -target 1.6
# List fiels which will be compiled and linked, together with
# additional dependencies.
@@ -52,7 +59,7 @@ src/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) $(DEFINES) $(CFLAGS_$(basename $(notdir $@))) -c $< -o $@
src/%.class: src/%.java
- javac -source 1.6 -target 1.6 -Xlint:all $^
+ javac $(JCFLAGS_$(basename $(notdir $@))) -Xlint:all $^
src/%: src/%.o
$(CXX) $(LDFLAGS) $^ -o $@ $(LIBS_$(notdir $@))
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 28/120: The version attribute is no longer
optional with Publican 3
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 5a960a532814154885a66f19335d7f4dba580d82
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Tue Jul 2 14:36:35 2013 +0200
The version attribute is no longer optional with Publican 3
---
defensive-coding/publican.cfg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defensive-coding/publican.cfg b/defensive-coding/publican.cfg
index 972f338..66e64a8 100644
--- a/defensive-coding/publican.cfg
+++ b/defensive-coding/publican.cfg
@@ -6,5 +6,5 @@ chunk_section_depth: 3
#mainfile: Defensive_Coding
#docname: Defensive_Coding
web_version_label: UNUSED
-#version: 1
+version: 1
#git_branch: eng-docs-rhel-6
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 27/120: Adjust the publican commands to
what is expected by Publican 3
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit a4eb06e0563550aaafb6f48a4200d4c34fbf56e4
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Tue Jul 2 14:36:15 2013 +0200
Adjust the publican commands to what is expected by Publican 3
---
defensive-coding/Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/defensive-coding/Makefile b/defensive-coding/Makefile
index f982a32..61f4ee5 100644
--- a/defensive-coding/Makefile
+++ b/defensive-coding/Makefile
@@ -12,16 +12,16 @@ build-snippets:
src/*.c src/*.cpp src/*.java src/*.py
build-manual: build-snippets
- publican build --format=html,epub,pdf --lang=en-US
+ publican build --formats=html,epub,pdf --langs=en-US
build-manual-html: build-snippets
- publican build --format=html --lang=en-US
+ publican build --formats=html --langs=en-US
build-manual-epub: build-snippets
- publican build --format=epub --lang=en-US
+ publican build --formats=epub --langs=en-US
build-manual-pdf: build-snippets
- publican build --format=pdf --lang=en-US
+ publican build --formats=pdf --langs=en-US
clean: clean-src
-rm -rf tmp
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 26/120: Chapter Cryptography: Fix typos
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit a7d76fd8eb9cfd7aad1ff95b22764728d47297cd
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Fri Jun 28 11:05:28 2013 +0200
Chapter Cryptography: Fix typos
---
defensive-coding/en-US/Tasks/Cryptography.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/defensive-coding/en-US/Tasks/Cryptography.xml b/defensive-coding/en-US/Tasks/Cryptography.xml
index 88f14a3..1bafc2a 100644
--- a/defensive-coding/en-US/Tasks/Cryptography.xml
+++ b/defensive-coding/en-US/Tasks/Cryptography.xml
@@ -7,7 +7,7 @@
<section>
<title>Primitives</title>
<para>
- Chosing from the following cryptographic primitives is
+ Choosing from the following cryptographic primitives is
recommended:
</para>
<itemizedlist>
@@ -50,7 +50,7 @@
<para>
The following facilities can be used to generate unpredictable
and non-repeating values. When these functions are used without
- special safeguards, each individual rnadom value should be at
+ special safeguards, each individual random value should be at
least 12 bytes long.
</para>
<itemizedlist>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months
[defensive-coding-guide] 16/120: Add documentation for parsing XML
with Qt
by git repository hosting
This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 38f436ea1c2633219e6b9f335c61b02aa35ce303
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Wed Apr 24 12:09:44 2013 +0200
Add documentation for parsing XML with Qt
---
defensive-coding/en-US/Tasks/Serialization.xml | 56 ++++++++++
.../Serialization-XML-Qt-NoEntityHandler.xml | 42 ++++++++
.../Serialization-XML-Qt-NoEntityReader.xml | 25 +++++
.../snippets/Serialization-XML-Qt-QDomDocument.xml | 16 +++
defensive-coding/src/.gitignore | 1 +
defensive-coding/src/XML-Parser-Qt.cpp | 120 +++++++++++++++++++++
defensive-coding/src/src.mk | 2 +
7 files changed, 262 insertions(+)
diff --git a/defensive-coding/en-US/Tasks/Serialization.xml b/defensive-coding/en-US/Tasks/Serialization.xml
index 60427c5..3d4abb1 100644
--- a/defensive-coding/en-US/Tasks/Serialization.xml
+++ b/defensive-coding/en-US/Tasks/Serialization.xml
@@ -255,6 +255,62 @@
</para>
</section>
+ <section id="sect-Defensive_Coding-Tasks-Serialization-Qt">
+ <title>Using Qt for XML parsing</title>
+ <para>
+ The XML component of Qt, QtXml, does not resolve external IDs
+ by default, so it is not requred to prevent such resolution.
+ Internal entities are processed, though. To change that, a
+ custom <literal>QXmlDeclHandler</literal> and
+ <literal>QXmlSimpleReader</literal> subclasses are needed. It
+ is not possible to use the
+ <function>QDomDocument::setContent(const QByteArray
+ &)</function> convenience methods.
+ </para>
+ <para>
+ <xref linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityHandler"/>
+ shows an entity handler which always returns errors, causing
+ parsing to stop when encountering entity declarations.
+ </para>
+ <example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityHandler">
+ <title>A QtXml entity handler which blocks entity processing</title>
+ <xi:include href="snippets/Serialization-XML-Qt-NoEntityHandler.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ This handler is used in the custom
+ <literal>QXmlReader</literal> subclass in <xref
+ linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityReader"/>.
+ Some parts of QtXml will call the
+ <function>setDeclHandler(QXmlDeclHandler *)</function> method.
+ Consequently, we prevent overriding our custom handler by
+ providing a definition of this method which does nothing. In
+ the constructor, we activate namespace processing; this part
+ may need adjusting.
+ </para>
+ <example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityReader">
+ <title>A QtXml XML reader which blocks entity processing</title>
+ <xi:include href="snippets/Serialization-XML-Qt-NoEntityReader.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ Our <literal>NoEntityReader</literal> class can be used with
+ one of the overloaded
+ <function>QDomDocument::setContent</function> methods.
+ <xref linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-QDomDocument"/>
+ shows how the <literal>buffer</literal> object (of type
+ <literal>QByteArray</literal>) is wrapped as a
+ <literal>QXmlInputSource</literal>. After calling the
+ <function>setContent</function> method, you should check the
+ return value and report any error.
+ </para>
+ <example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-QDomDocument">
+ <title>Parsing an XML document with QDomDocument, without entity expansion</title>
+ <xi:include href="snippets/Serialization-XML-Qt-QDomDocument.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ </section>
+
<section id="sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse">
<title>Using OpenJDK for XML parsing and validation</title>
<para>
diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityHandler.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityHandler.xml
new file mode 100644
index 0000000..3a5ef31
--- /dev/null
+++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityHandler.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+class NoEntityHandler : public QXmlDeclHandler {
+public:
+ bool attributeDecl(const QString&, const QString&, const QString&,
+ const QString&, const QString&);
+ bool internalEntityDecl(const QString&, const QString&);
+ bool externalEntityDecl(const QString&, const QString&,
+ const QString&);
+ QString errorString() const;
+};
+
+ bool
+NoEntityHandler::attributeDecl
+ (const QString&, const QString&, const QString&, const QString&,
+ const QString&)
+{
+ return false;
+}
+
+bool
+NoEntityHandler::internalEntityDecl(const QString&, const QString&)
+{
+ return false;
+}
+
+bool
+NoEntityHandler::externalEntityDecl(const QString&, const QString&, const
+ QString&)
+{
+ return false;
+}
+
+QString
+NoEntityHandler::errorString() const
+{
+ return "XML declaration not permitted";
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityReader.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityReader.xml
new file mode 100644
index 0000000..0a70fa4
--- /dev/null
+++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-NoEntityReader.xml
@@ -0,0 +1,25 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+class NoEntityReader : public QXmlSimpleReader {
+ NoEntityHandler handler;
+public:
+ NoEntityReader();
+ void setDeclHandler(QXmlDeclHandler *);
+};
+
+ NoEntityReader::NoEntityReader()
+{
+ QXmlSimpleReader::setDeclHandler(&handler);
+ setFeature("http://xml.org/sax/features/namespaces", true);
+ setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ }
+
+void
+NoEntityReader::setDeclHandler(QXmlDeclHandler *)
+{
+ // Ignore the handler which was passed in.
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-QDomDocument.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-QDomDocument.xml
new file mode 100644
index 0000000..ff0e056
--- /dev/null
+++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Qt-QDomDocument.xml
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+NoEntityReader reader;
+QBuffer buffer(&data);
+buffer.open(QIODevice::ReadOnly);
+QXmlInputSource source(&buffer);
+QDomDocument doc;
+QString errorMsg;
+int errorLine;
+int errorColumn;
+bool okay = doc.setContent
+ (&source, &reader, &errorMsg, &errorLine, &errorColumn);
+</programlisting>
diff --git a/defensive-coding/src/.gitignore b/defensive-coding/src/.gitignore
index 2f86977..4adbfe5 100644
--- a/defensive-coding/src/.gitignore
+++ b/defensive-coding/src/.gitignore
@@ -3,5 +3,6 @@
/TLS-Client-NSS
/TLS-Client-OpenSSL
/XML-Parser-Expat
+/XML-Parser-Qt
*.class
*.o
diff --git a/defensive-coding/src/XML-Parser-Qt.cpp b/defensive-coding/src/XML-Parser-Qt.cpp
new file mode 100644
index 0000000..e4c970e
--- /dev/null
+++ b/defensive-coding/src/XML-Parser-Qt.cpp
@@ -0,0 +1,120 @@
+#include <QtCore/QBuffer>
+#include <QtCore/QByteArray>
+#include <QtCore/QFile>
+#include <QtXml/QDomDocument>
+#include <QtXml/QXmlSimpleReader>
+
+#include <stdio.h>
+
+namespace {
+ //+ Tasks Serialization-XML-Qt-NoEntityHandler
+ class NoEntityHandler : public QXmlDeclHandler {
+ public:
+ bool attributeDecl(const QString&, const QString&, const QString&,
+ const QString&, const QString&);
+ bool internalEntityDecl(const QString&, const QString&);
+ bool externalEntityDecl(const QString&, const QString&,
+ const QString&);
+ QString errorString() const;
+ };
+
+ bool
+ NoEntityHandler::attributeDecl
+ (const QString&, const QString&, const QString&, const QString&,
+ const QString&)
+ {
+ return false;
+ }
+
+ bool
+ NoEntityHandler::internalEntityDecl(const QString&, const QString&)
+ {
+ return false;
+ }
+
+ bool
+ NoEntityHandler::externalEntityDecl(const QString&, const QString&, const
+ QString&)
+ {
+ return false;
+ }
+
+ QString
+ NoEntityHandler::errorString() const
+ {
+ return "XML declaration not permitted";
+ }
+ //-
+
+ //+ Tasks Serialization-XML-Qt-NoEntityReader
+ class NoEntityReader : public QXmlSimpleReader {
+ NoEntityHandler handler;
+ public:
+ NoEntityReader();
+ void setDeclHandler(QXmlDeclHandler *);
+ };
+
+ NoEntityReader::NoEntityReader()
+ {
+ QXmlSimpleReader::setDeclHandler(&handler);
+ setFeature("http://xml.org/sax/features/namespaces", true);
+ setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ }
+
+ void
+ NoEntityReader::setDeclHandler(QXmlDeclHandler *)
+ {
+ // Ignore the handler which was passed in.
+ }
+ //-
+}
+
+
+int
+main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s XML-FILE\n", argv[0]);
+ return 1;
+ }
+
+ QByteArray data;
+ {
+ QFile f(argv[1]);
+ if (!f.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "error: could not open file: %s\n", argv[1]);
+ return 1;
+ }
+ data = f.readAll();
+ if (f.error()) {
+ fprintf(stderr, "error: could not read file: %s\n", argv[1]);
+ return 1;
+ }
+ }
+
+ //+ Tasks Serialization-XML-Qt-QDomDocument
+ NoEntityReader reader;
+ QBuffer buffer(&data);
+ buffer.open(QIODevice::ReadOnly);
+ QXmlInputSource source(&buffer);
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ bool okay = doc.setContent
+ (&source, &reader, &errorMsg, &errorLine, &errorColumn);
+ //-
+ if (!okay) {
+ fprintf(stderr, "%d:%d: %s\n", errorLine, errorColumn,
+ errorMsg.toUtf8().constData());
+ return 1;
+ }
+
+ data = doc.toByteArray(1);
+ if (fwrite(data.constData(), data.size(), 1, stdout) != 1) {
+ perror("fwrite");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index 4212094..f2eac6f 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -28,6 +28,8 @@ CFLAGS_TLS-Client-NSS = -I/usr/include/nspr4 -I/usr/include/nss3
LIBS_TLS-Client-NSS = -lnss3 -lnspr4 -lssl3
compile_and_link += XML-Parser-Expat
LIBS_XML-Parser-Expat = -lexpat
+compile_and_link += XML-Parser-Qt
+LIBS_XML-Parser-Qt = -lQtCore -lQtXml
# Define preprocessor symbols if certain functions exist.
CHECK_FUNCTION = crypto/X509_check_host/-DHAVE_X509_CHECK_HOST \
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
7 years, 8 months