[Secure Coding] master: Add chapter on Go (13faeec)

fweimer at fedoraproject.org fweimer at fedoraproject.org
Mon May 26 12:58:29 UTC 2014


Repository : http://git.fedorahosted.org/git/?p=secure-coding.git

On branch  : master

>---------------------------------------------------------------

commit 13faeec63da544dd64c453a5fd810f7b6d758dbd
Author: Florian Weimer <fweimer at redhat.com>
Date:   Mon May 26 14:58:01 2014 +0200

    Add chapter on Go


>---------------------------------------------------------------

 defensive-coding/Makefile                   |    2 +-
 defensive-coding/en-US/Defensive_Coding.xml |    1 +
 defensive-coding/en-US/Go.xml               |   90 +++++++++++++++++++++++++++
 defensive-coding/src/.gitignore             |    1 +
 defensive-coding/src/Go-Error_Handling.go   |   48 ++++++++++++++
 defensive-coding/src/src.mk                 |    6 ++
 6 files changed, 147 insertions(+), 1 deletions(-)

diff --git a/defensive-coding/Makefile b/defensive-coding/Makefile
index 6220afc..2090dad 100644
--- a/defensive-coding/Makefile
+++ b/defensive-coding/Makefile
@@ -9,7 +9,7 @@ build: build-src build-manual
 build-snippets:
 	mkdir -p en-US/snippets
 	python scripts/split-snippets.py . \
-	  src/*.c src/*.cpp src/*.java src/*.py
+	  src/*.c src/*.cpp src/*.java src/*.py src/*.go
 
 build-manual: build-snippets
 	publican build --formats=html,epub,pdf --langs=en-US
diff --git a/defensive-coding/en-US/Defensive_Coding.xml b/defensive-coding/en-US/Defensive_Coding.xml
index a9baeb3..ee96c8d 100644
--- a/defensive-coding/en-US/Defensive_Coding.xml
+++ b/defensive-coding/en-US/Defensive_Coding.xml
@@ -8,6 +8,7 @@
     <xi:include href="CXX.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
     <xi:include href="Java.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
     <xi:include href="Python.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+    <xi:include href="Go.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
     <xi:include href="Vala.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
   </part>
   <part>
diff --git a/defensive-coding/en-US/Go.xml b/defensive-coding/en-US/Go.xml
new file mode 100644
index 0000000..0e44d5e
--- /dev/null
+++ b/defensive-coding/en-US/Go.xml
@@ -0,0 +1,90 @@
+<?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-Go">
+<title>The Go Programming Language</title>
+<para>
+  This chapter contains language-specific recommendations for Go.
+</para>
+<section id="chap-Defensive_Coding-Go-Memory_Safety">
+  <title>Memory safety</title>
+  <para>
+    Go provides memory safety, but only if the program is not executed
+    in parallel (that is, <envar>GOMAXPROCS</envar> is not larger than
+    <literal>1</literal>).  The reason is that interface values and
+    slices consist of multiple words are not updated atomically.
+    Another thread of execution can observe an inconsistent pairing
+    between type information and stored value (for interfaces) or
+    pointer and length (for slices), and such inconsistency can lead
+    to a memory safety violation.
+  </para>
+  <para>
+    Code which does not run in parallel and does not use the
+    <literal>unsafe</literal> package (or other packages which expose
+    unsafe constructs) is memory-safe.  For example, invalid casts and
+    out-of-range subscripting cause panics and run time.
+  </para>
+  <para>
+    Keep in mind that finalization can introduce parallelism because
+    finalizers are executed concurrently, potentially interleaved with
+    the rest of the program.
+  </para>
+</section>
+<section id="chap-Defensive_Coding-Go-Error_Handling">
+  <title>Error handling</title>
+  <para>
+    Only a few common operations (such as pointer dereference, integer
+    division, array subscripting) trigger exceptions in Go, called
+    <emphasis>panics</emphasis>.  Most interfaces in the standard
+    library use a separate return value of type
+    <literal>error</literal> to signal error.
+  </para>
+  <para>
+    Not checking error return values can lead to incorrect operation
+    and data loss (especially in the case of writes, using interfaces
+    such as <literal>io.Writer</literal>).
+  </para>
+  <para>
+    The correct way to check error return values depends on the
+    function or method being called.  In the majority of cases, the
+    first step after calling a function should be an error check
+    against the <literal>nil</literal> value, handling any encountered
+    error.  See <xref
+    linkend="ex-Defensive_Coding-Go-Error_Handling-Regular"/> for
+    details.
+  </para>
+  <example id="ex-Defensive_Coding-Go-Error_Handling-Regular">
+    <title>Regular error handling in Go</title>
+    <xi:include href="snippets/Go-Error_Handling-Regular.xml"
+		xmlns:xi="http://www.w3.org/2001/XInclude" />
+  </example>
+  <para>
+    However, with <literal>io.Reader</literal>,
+    <literal>io.ReaderAt</literal> and related interfaces, it is
+    necessary to check for a non-zero number of read bytes first, as
+    shown in <xref
+    linkend="ex-Defensive_Coding-Go-Error_Handling-IO"/>.  If this
+    pattern is not followed, data loss may occur.  This is due to the
+    fact that the <literal>io.Reader</literal> interface permits
+    returning both data and an error at the same time.
+  </para>
+  <example id="ex-Defensive_Coding-Go-Error_Handling-IO">
+    <title>Read error handling in Go</title>
+    <xi:include href="snippets/Go-Error_Handling-IO.xml"
+		xmlns:xi="http://www.w3.org/2001/XInclude" />
+  </example>
+</section>
+<section id="chap-Defensive_Coding-Go-Garbage_Collector">
+  <title>Garbage Collector</title>
+  <para>
+    Older Go releases (before Go 1.3) use a conservative garbage
+    collector without blacklisting.  This means that data blobs can
+    cause retention of unrelated data structures because the data is
+    conservatively interpreted as pointers.  This phenomenon can be
+    triggered accidentally on 32-bit architectures and is more likely
+    to occur if the heap grows larger.  On 64-bit architectures, it
+    may be possible to trigger it deliberately—it is unlikely to occur
+    spontaneously.
+  </para>
+</section>
+</chapter>
diff --git a/defensive-coding/src/.gitignore b/defensive-coding/src/.gitignore
index 4adbfe5..335a122 100644
--- a/defensive-coding/src/.gitignore
+++ b/defensive-coding/src/.gitignore
@@ -4,5 +4,6 @@
 /TLS-Client-OpenSSL
 /XML-Parser-Expat
 /XML-Parser-Qt
+/Go-Error_Handling
 *.class
 *.o
diff --git a/defensive-coding/src/Go-Error_Handling.go b/defensive-coding/src/Go-Error_Handling.go
new file mode 100644
index 0000000..d546018
--- /dev/null
+++ b/defensive-coding/src/Go-Error_Handling.go
@@ -0,0 +1,48 @@
+package main
+
+import "io"
+
+//+ Go Error_Handling-Regular
+type Processor interface {
+	Process(buf []byte) (message string, err error)
+}
+
+type ErrorHandler interface {
+	Handle(err error)
+}
+
+func RegularError(buf []byte, processor Processor,
+	handler ErrorHandler) (message string, err error) {
+	message, err = processor.Process(buf)
+	if err != nil {
+		handler.Handle(err)
+		return "", err
+	}
+	return
+}
+//-
+
+//+ Go Error_Handling-IO
+func IOError(r io.Reader, buf []byte, processor Processor,
+	handler ErrorHandler) (message string, err error) {
+	n, err := r.Read(buf)
+	// First check for available data.
+	if n > 0 {
+		message, err = processor.Process(buf[0:n])
+		// Regular error handling.
+		if err != nil {
+			handler.Handle(err)
+			return "", err
+		}
+	}
+	// Then handle any error.
+	if err != nil {
+		handler.Handle(err)
+		return "", err
+	}
+	return
+}
+//-
+
+func main() {
+}
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index d47fc09..18bd592 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -2,10 +2,12 @@
 
 CC = gcc
 CXX = g++
+GCCGO = gccgo
 CWARNFLAGS = -Wall -W -Wno-unused-parameter -Werror=implicit-function-declaration
 CXXWARNFLAGS = -Wall -W
 CFLAGS = -std=gnu99 -O2 $(CWARNFLAGS) -g
 CXXFLAGS = -std=c++03 -O2 $(CXXWARNFLAGS) -g
+GOFLAGS = -O2 -Wall -W
 LDFLAGS = -g
 
 # List files which should only be compiled for syntax checking.
@@ -41,6 +43,7 @@ compile_and_link += XML-Parser-Expat
 LIBS_XML-Parser-Expat = -lexpat
 compile_and_link += XML-Parser-Qt
 LIBS_XML-Parser-Qt = -lQtCore -lQtXml
+compile_and_link += Go-Error_Handling
 
 # Define preprocessor symbols if certain functions exist.
 CHECK_FUNCTION = crypto/X509_check_host/-DHAVE_X509_CHECK_HOST \
@@ -68,6 +71,9 @@ src/%.class: src/%.java
 src/%: src/%.o
 	$(CXX) $(LDFLAGS) $^ -o $@ $(LIBS_$(notdir $@))
 
+src/%: src/%.go
+	$(GCCGO) $(GOFLAGS) $(LDFLAGS) -o $@ $^
+
 src/TLS-Client-GNUTLS: src/tcp_connect.o
 src/TLS-Client-OpenSSL: src/tcp_connect.o src/x509_check_host.o
 src/TLS-Client-NSS: src/tcp_connect.o



More information about the security mailing list