Add UsefulBuf example code (#136)

* fix grammer in security policy

* first check-in of UsefulBuf example

* Code tidy, comment wording, spelling...

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/ub-example.c b/ub-example.c
new file mode 100644
index 0000000..5c9b6f5
--- /dev/null
+++ b/ub-example.c
@@ -0,0 +1,260 @@
+/* =========================================================================
+   ub-example.c -- Example code for UsefulBuf
+
+   Copyright (c) 2022, Laurence Lundblade. All rights reserved.
+
+   SPDX-License-Identifier: BSD-3-Clause
+
+   See BSD-3-Clause license in README.md
+
+   Created on 4/8/22
+  ========================================================================== */
+
+#include "ub-example.h"
+
+#include "UsefulBuf.h"
+
+
+/*
+ * A considerable number of the security issues with C code come from
+ * mistakes made with pointers and lengths.  UsefulBuf adopts a
+ * convention that a pointer and length *always* go together to help
+ * mitigate this.  With UsefulBuf there are never pointers without
+ * lengths, so you always know how big a buffer or some binary data
+ * is.
+ *
+ * C99 allows passing structures so a structure is used. Compilers are
+ * smart these days so the object code produced is little different
+ * than passing two separate parameters. Passing structures also makes
+ * the interfaces prettier. Assignments of structures also can make
+ * code prettier.
+ *
+ * ALong with the UsefulBuf structure, there are a bunch of (tested!)
+ * functions to manipulate them so code using it may have no pointer
+ * manipulation at all.
+ *
+ * Constness is also a useful and desirous thing. See
+ * https://stackoverflow.com/questions/117293/use-of-const-for-function-parameters
+ * Keeping const distinct from non-const is helpful when reading the
+ * code and helps avoid some coding mistakes.  In this example the
+ * buffers filled in with data are const and the ones that are
+ * to-be-filled in are not const.
+ *
+ * This contrived example copies data from input to output expanding
+ * bytes with the value 'x' to 'xx'.
+ *
+ * Input -- This is the pointer and length of the input, the bytes to
+ * copy. Note that UsefulBufC.ptr is a const void * indicating that
+ * input data won't be changed by this function.  There is a "C" in
+ * "UsefulBufC "to indicate the value is const.  The length here is
+ * the length of the valid input data. Note also that the parameter
+ * Input is const, so this is fully const and clearly an [in]
+ * parameter.
+ *
+ * OutputBuffer -- This is a pointer and length of the memory to be
+ * used to store the output. The correct length here is critical for
+ * code security. Note that UsefulBuf.ptr is void *, it is not const
+ * indicating data can be written to it. Note that the parameter
+ * itself *is* const indicating that the code below will not point
+ * this to some other buffer or change the length and clearly marking
+ * it as an [in] parameter.
+ *
+ * Output -- This is the interesting and unusual one. To stay
+ * consistent with always pairing a length and a pointer, this is
+ * returned as a UsefulBuC. Also, to stay consistent with valid data
+ * being const, it is a UsefulBufC, not a UsefulBuf. It is however, an
+ * [out] parameter so the parameter is a pointer to a UsefulBufC.
+ *
+ * In this case and most cases, the pointer in Output->ptr will be the
+ * same as OutputBuffer.ptr. This may seem redundant, but there are a
+ * few reasons for it. First, is the goal of always pairing a pointer
+ * and a length.  Second is being more strict and correct with
+ * constness. Third is the code hygiene and clarity of having
+ * variables for to-be-filled buffers be distinct from those
+ * containing valid data. Fourth, there are no [in,out] parameters,
+ * only [in] parameters and [out] parameters (the to-be-filled-in
+ * buffer is considered an [in] parameter).
+ *
+ * Note that the compiler will be smart and should generate pretty
+ * much the same code as for a traditional interface. On x86 with
+ * gcc-11 and no stack guards, the UB code is 81 bytes and the
+ * traditional code is 77 bytes.
+ *
+ * Finally, this supports computing of the length of the would-be
+ * output without actually doing any outputting. Pass {NULL, SIZE_MAX}
+ * for the OutputBuffer and the length will be returned in Output.
+ */
+int
+ExpandxUB(const UsefulBufC   Input,
+          const UsefulBuf    OutputBuffer,
+          UsefulBufC        *Output)
+{
+    size_t nInputPosition;
+    size_t nOutputPosition;
+
+    nOutputPosition = 0;
+
+    /* Loop over all the bytes in Input */
+    for(nInputPosition = 0; nInputPosition < Input.len; nInputPosition++) {
+        const uint8_t nInputByte = ((uint8_t*)Input.ptr)[nInputPosition];
+
+        /* Copy every byte */
+        if(OutputBuffer.ptr != NULL) {
+            ((uint8_t *)OutputBuffer.ptr)[nOutputPosition] = nInputByte;
+        }
+        nOutputPosition++;
+        if(nOutputPosition >= OutputBuffer.len) {
+            return -1;
+        }
+
+        /* Double output 'x' because that is what this contrived example does */
+        if(nInputByte== 'x') {
+            if(OutputBuffer.ptr != NULL) {
+                ((uint8_t *)OutputBuffer.ptr)[nOutputPosition] = 'x';
+            }
+            nOutputPosition++;
+            if(nOutputPosition >= OutputBuffer.len) {
+                return -1;
+            }
+        }
+    }
+
+    *Output = (UsefulBufC){OutputBuffer.ptr, nOutputPosition};
+
+    return 0; /* success */
+}
+
+
+/* This is the more tradional way to implement this. */
+int
+ExpandxTraditional(const uint8_t  *pInputPointer,
+                   const size_t    uInputLength,
+                   uint8_t        *pOutputBuffer,
+                   const size_t    uOutputBufferLength,
+                   size_t         *puOutputLength)
+{
+    size_t nInputPosition;
+    size_t nOutputPosition;
+
+    nOutputPosition = 0;
+
+    /* Loop over all the bytes in Input */
+    for(nInputPosition = 0; nInputPosition < uInputLength; nInputPosition++) {
+        const uint8_t nInputByte = ((uint8_t*)pInputPointer)[nInputPosition];
+
+        /* Copy every byte */
+        if(pOutputBuffer != NULL) {
+            ((uint8_t *)pOutputBuffer)[nOutputPosition] = nInputByte;
+        }
+        nOutputPosition++;
+        if(nOutputPosition >= uOutputBufferLength) {
+            return -1;
+        }
+
+        /* Double output 'x' because that is what this contrived example does */
+        if(nInputByte== 'x') {
+            if(pOutputBuffer != NULL) {
+                ((uint8_t *)pOutputBuffer)[nOutputPosition] = 'x';
+            }
+            nOutputPosition++;
+            if(nOutputPosition >= uOutputBufferLength) {
+                return -1;
+            }
+        }
+    }
+
+   *puOutputLength = nOutputPosition;
+
+    return 0; /* success */
+}
+
+
+/*
+ * Here's an example of going from a traditional interface
+ * interface to a UsefulBuf interface.
+ */
+int
+ExpandxTraditionalAdaptor(const uint8_t  *pInputPointer,
+                          size_t          uInputLength,
+                          uint8_t        *pOutputBuffer,
+                          size_t          uOutputBufferLength,
+                          size_t         *puOutputLength)
+{
+    UsefulBufC  Input;
+    UsefulBuf   OutputBuffer;
+    UsefulBufC  Output;
+    int         nReturn;
+
+    Input = (UsefulBufC){pInputPointer, uInputLength};
+    OutputBuffer = (UsefulBuf){pOutputBuffer, uOutputBufferLength};
+
+    nReturn = ExpandxUB(Input, OutputBuffer, &Output);
+
+    *puOutputLength = Output.len;
+
+    return nReturn;
+}
+
+
+/* Here's an example for going from a UsefulBuf interface
+ to a traditional interface. */
+int
+ExpandxUBAdaptor(const UsefulBufC   Input,
+                 const UsefulBuf    OutputBuffer,
+                 UsefulBufC        *Output)
+{
+   Output->ptr = OutputBuffer.ptr;
+
+   return ExpandxTraditional(Input.ptr, Input.len,
+                             OutputBuffer.ptr, OutputBuffer.len,
+                           &(Output->len));
+}
+
+
+
+#define INPUT "xyz123xyz"
+
+int32_t RunUsefulBufExample()
+{
+   /* ------------ UsefulBuf examples ------------- */
+   UsefulBufC Input = UsefulBuf_FROM_SZ_LITERAL(INPUT);
+
+   /* This macros makes a 20 byte buffer on the stack. It also makes
+    * a UsefulBuf on the stack. It sets up the UsefulBuf to point to
+    * the 20 byte buffer and sets it's length to 20 bytes. This
+    * is the empty, to-be-filled in memory for the output. It is not
+    * const. */
+   MakeUsefulBufOnStack(OutBuf, sizeof(INPUT) * 2);
+
+   /* This is were the pointer and the length of the completed output
+    * will be placed. Output.ptr is a pointer to const bytes. */
+   UsefulBufC           Output;
+
+   ExpandxUB(Input, OutBuf, &Output);
+
+   ExpandxUBAdaptor(Input, OutBuf, &Output);
+
+
+
+   /* ------ Get Size example  -------- */
+   ExpandxUB(Input, (UsefulBuf){NULL, SIZE_MAX}, &Output);
+
+   /* Size is in Output.len */
+
+
+
+   /* ---------- Traditional examples (for comparison) --------- */
+   uint8_t puBuffer[sizeof(INPUT) * 2];
+   size_t  uOutputSize;
+
+   ExpandxTraditional((const uint8_t *)INPUT, sizeof(INPUT),
+                     puBuffer, sizeof(puBuffer),
+                     &uOutputSize);
+
+
+   ExpandxTraditionalAdaptor((const uint8_t *)INPUT, sizeof(INPUT),
+                            puBuffer, sizeof(puBuffer),
+                           &uOutputSize);
+
+   return 0;
+}