[git] GPG-ERROR - branch, master, updated. libgpg-error-1.26-9-g4bfc211

by NIIBE Yutaka cvs at cvs.gnupg.org
Thu Feb 2 11:57:18 CET 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Error codes used by GnuPG et al.".

The branch, master has been updated
       via  4bfc2117b70415a5c5d3f0a0ac9086e168350d83 (commit)
      from  55c497904dd0794ca5cfcafe369943736b0d4e62 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4bfc2117b70415a5c5d3f0a0ac9086e168350d83
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Feb 1 19:45:39 2017 +0900

    Add Base64 decoder.
    
    * NEWS: Add interface changes.
    * src/Makefile.am (libgpg_error_la_SOURCES): Add b64dec.c.
    * src/b64dec.c: New.  Taken from gpgme.  Prefix function names with
    _gpgrt_.  Change API a bit, not exposing the structure.
    * src/gpg-error.def.in: Export Base64 functions.
    * src/gpg-error.vers: Likewise.
    * src/visibility.c, src/visibility.h: Likewise.
    * src/gpg-error.h.in: Add Base64 struct and functions.
    * src/gpgrt-int.h: Add Base64 internal functions.
    * tests/Makefile.am (TESTS): Add t-b64dec.
    * tests/t-b64dec.c: New.
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/NEWS b/NEWS
index 572385f..912dd0c 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,13 @@ Noteworthy changes in version 1.27 (unreleased) [C2_/A2_/R_]
 
  * Fixed macro GPGRT_GCC_VERSION.
 
+ * Interface changes relative to the 1.26 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgrt_b64state_t                 NEW type.
+ gpgrt_b64dec_start               NEW.
+ gpgrt_b64dec_proc                NEW.
+ gpgrt_b64dec_finish              NEW.
+
 
 Noteworthy changes in version 1.26 (2016-12-21) [C21/A21/R0]
 -----------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 1eb8287..d849c42 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -179,7 +179,7 @@ libgpg_error_la_SOURCES = gettext.h $(arch_sources) \
 	gpgrt-int.h init.c init.h version.c lock.h thread.h \
 	estream.c estream-printf.c estream-printf.h \
 	strsource.c strerror.c code-to-errno.c code-from-errno.c \
-	visibility.c visibility.h
+	visibility.c visibility.h b64dec.c
 nodist_libgpg_error_la_SOURCES = gpg-error.h
 
 # libgpg_error_la_DEPENDENCIES = \
diff --git a/src/b64dec.c b/src/b64dec.c
new file mode 100644
index 0000000..d846a6a
--- /dev/null
+++ b/src/b64dec.c
@@ -0,0 +1,279 @@
+/* b64dec.c - Simple Base64 decoder.
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011, 2016 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gpgrt-int.h"
+
+struct _gpgrt_b64state
+{
+  int idx;
+  int quad_count;
+  char *title;
+  unsigned char radbuf[4];
+  int stop_seen:1;
+  int invalid_encoding:1;
+  gpg_error_t lasterr;
+};
+
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[128] =
+  {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+    0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+    0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+    0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+  };
+
+enum decoder_states
+  {
+    s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
+    s_b64_0, s_b64_1, s_b64_2, s_b64_3,
+    s_waitendtitle, s_waitend
+  };
+
+
+
+/* Allocate and initialize the context for the base64 decoder.  If
+   TITLE is NULL a plain base64 decoding is done.  If it is the empty
+   string the decoder will skip everything until a "-----BEGIN " line
+   has been seen, decoding ends at a "----END " line.  */
+gpgrt_b64state_t
+_gpgrt_b64dec_start (const char *title)
+{
+  gpgrt_b64state_t state;
+  char *t = NULL;
+
+  if (title)
+    {
+      t = strdup (title);
+      if (!t)
+        return NULL;
+    }
+
+  state = calloc (1, sizeof (struct _gpgrt_b64state));
+  if (!state)
+    {
+      free (t);
+      return NULL;
+    }
+
+  if (t)
+    {
+      state->title = t;
+      state->idx = s_init;
+    }
+  else
+    state->idx = s_b64_0;
+
+  return state;
+}
+
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Stores the
+   new length of the buffer at R_NBYTES. */
+gpg_error_t
+_gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length,
+                    size_t *r_nbytes)
+{
+  enum decoder_states ds = state->idx;
+  unsigned char val = state->radbuf[0];
+  int pos = state->quad_count;
+  char *d, *s;
+
+  if (state->lasterr)
+    return state->lasterr;
+
+  if (state->stop_seen)
+    {
+      *r_nbytes = 0;
+      state->lasterr = gpg_error (GPG_ERR_EOF);
+      free (state->title);
+      state->title = NULL;
+      return state->lasterr;
+    }
+
+  for (s=d=buffer; length && !state->stop_seen; length--, s++)
+    {
+    again:
+      switch (ds)
+        {
+        case s_idle:
+          if (*s == '\n')
+            {
+              ds = s_lfseen;
+              pos = 0;
+            }
+          break;
+        case s_init:
+          ds = s_lfseen;
+        case s_lfseen:
+          if (*s != "-----BEGIN "[pos])
+            {
+              ds = s_idle;
+              goto again;
+            }
+          else if (pos == 10)
+            {
+              pos = 0;
+              ds = s_beginseen;
+            }
+          else
+            pos++;
+          break;
+        case s_beginseen:
+          if (*s != "PGP "[pos])
+            ds = s_begin; /* Not a PGP armor.  */
+          else if (pos == 3)
+            ds = s_waitheader;
+          else
+            pos++;
+          break;
+        case s_waitheader:
+          if (*s == '\n')
+            ds = s_waitblank;
+          break;
+        case s_waitblank:
+          if (*s == '\n')
+            ds = s_b64_0; /* blank line found.  */
+          else if (*s == ' ' || *s == '\r' || *s == '\t')
+            ; /* Ignore spaces. */
+          else
+            {
+              /* Armor header line.  Note that we don't care that our
+               * FSM accepts a header prefixed with spaces.  */
+              ds = s_waitheader; /* Wait for next header.  */
+            }
+          break;
+        case s_begin:
+          if (*s == '\n')
+            ds = s_b64_0;
+          break;
+        case s_b64_0:
+        case s_b64_1:
+        case s_b64_2:
+        case s_b64_3:
+          {
+            int c;
+
+            if (*s == '-' && state->title)
+              {
+                /* Not a valid Base64 character: assume end
+                   header.  */
+                ds = s_waitend;
+              }
+            else if (*s == '=')
+              {
+                /* Pad character: stop */
+                if (ds == s_b64_1)
+                  *d++ = val;
+                ds = state->title? s_waitendtitle : s_waitend;
+              }
+            else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+              ; /* Skip white spaces. */
+            else if ( (*s & 0x80)
+                      || (c = asctobin[*(unsigned char *)s]) == 255)
+              {
+                /* Skip invalid encodings.  */
+                state->invalid_encoding = 1;
+              }
+            else if (ds == s_b64_0)
+              {
+                val = c << 2;
+                ds = s_b64_1;
+              }
+            else if (ds == s_b64_1)
+              {
+                val |= (c>>4)&3;
+                *d++ = val;
+                val = (c<<4)&0xf0;
+                ds = s_b64_2;
+              }
+            else if (ds == s_b64_2)
+              {
+                val |= (c>>2)&15;
+                *d++ = val;
+                val = (c<<6)&0xc0;
+                ds = s_b64_3;
+              }
+            else
+              {
+                val |= c&0x3f;
+                *d++ = val;
+                ds = s_b64_0;
+              }
+          }
+          break;
+        case s_waitendtitle:
+          if (*s == '-')
+            ds = s_waitend;
+          break;
+        case s_waitend:
+          if ( *s == '\n')
+            state->stop_seen = 1;
+          break;
+        default:
+          assert (!"invalid state");
+        }
+    }
+
+
+  state->idx = ds;
+  state->radbuf[0] = val;
+  state->quad_count = pos;
+  *r_nbytes = (d -(char*) buffer);
+  return 0;
+}
+
+
+/* Return an error code in case an encoding error has been found
+   during decoding. */
+gpg_error_t
+_gpgrt_b64dec_finish (gpgrt_b64state_t state)
+{
+  gpg_error_t err;
+
+  if (state->lasterr)
+    err = state->lasterr;
+  else
+    {
+      free (state->title);
+      err = state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
+    }
+  free (state);
+
+  return err;
+}
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index 19e87fa..ad65f8c 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -152,4 +152,8 @@ EXPORTS
 
  gpgrt_get_syscall_clamp      @112
 
+ gpgrt_b64dec_start           @113
+ gpgrt_b64dec_proc            @114
+ gpgrt_b64dec_finish          @115
+
 ;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index c603314..19bdeed 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -853,6 +853,16 @@ int gpgrt_vsnprintf (char *buf,size_t bufsize,
 # define es_bsprintf          gpgrt_bsprintf
 # define es_vbsprintf         gpgrt_vbsprintf
 #endif /*GPGRT_ENABLE_ES_MACROS*/
+

+/* Base64 decode functions.  */
+
+struct _gpgrt_b64state;
+typedef struct _gpgrt_b64state *gpgrt_b64state_t;
+
+gpgrt_b64state_t gpgrt_b64dec_start (const char *title);
+gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state,
+                               void *buffer, size_t length, size_t *r_nbytes);
+gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state);
 
 #ifdef __cplusplus
 }
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 802ff3d..e44128c 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -126,6 +126,10 @@ GPG_ERROR_1.0 {
     gpg_err_deinit;
     gpgrt_set_alloc_func;
 
+    gpgrt_b64dec_start;
+    gpgrt_b64dec_proc;
+    gpgrt_b64dec_finish;
+
   local:
     *;
 };
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index fba2585..d624e84 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -312,4 +312,10 @@ int _gpgrt_w32_pollable_create (void *_GPGRT__RESTRICT *_GPGRT__RESTRICT cookie,
 int _gpgrt_w32_poll (gpgrt_poll_t *fds, size_t nfds, int timeout);
 #endif
 
+gpgrt_b64state_t _gpgrt_b64dec_start (const char *title);
+gpg_error_t _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer,
+                                size_t length, size_t *r_nbytes);
+gpg_error_t _gpgrt_b64dec_finish (gpgrt_b64state_t state);
+
+
 #endif /*_GPGRT_GPGRT_INT_H*/
diff --git a/src/visibility.c b/src/visibility.c
index 89b5623..b637e7a 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -711,3 +711,22 @@ gpgrt_vsnprintf (char *buf, size_t bufsize,
 {
   return _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr);
 }
+
+gpgrt_b64state_t
+gpgrt_b64dec_start (const char *title)
+{
+  return _gpgrt_b64dec_start (title);
+}
+
+gpg_error_t
+gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer,
+                   size_t length, size_t *r_nbytes)
+{
+  return _gpgrt_b64dec_proc (state, buffer, length, r_nbytes);
+}
+
+gpg_error_t
+gpgrt_b64dec_finish (gpgrt_b64state_t state)
+{
+  return _gpgrt_b64dec_finish (state);
+}
diff --git a/src/visibility.h b/src/visibility.h
index 479186f..da8e228 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -145,6 +145,10 @@ MARK_VISIBLE (gpgrt_set_syscall_clamp)
 MARK_VISIBLE (gpgrt_get_syscall_clamp)
 MARK_VISIBLE (gpgrt_set_alloc_func)
 
+MARK_VISIBLE (gpgrt_b64dec_start)
+MARK_VISIBLE (gpgrt_b64dec_proc)
+MARK_VISIBLE (gpgrt_b64dec_finish)
+
 #undef MARK_VISIBLE
 
 #else /*!_GPGRT_INCL_BY_VISIBILITY_C*/
@@ -255,6 +259,9 @@ MARK_VISIBLE (gpgrt_set_alloc_func)
 #define gpgrt_get_syscall_clamp     _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_set_alloc_func        _gpgrt_USE_UNDERSCORED_FUNCTION
 
+#define gpgrt_b64dec_start          _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_b64dec_proc           _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_b64dec_finish         _gpgrt_USE_UNDERSCORED_FUNCTION
 
 #endif /*!_GPGRT_INCL_BY_VISIBILITY_C*/
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 92b97f2..a3c6cbd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -27,7 +27,7 @@ endif
 
 gpg_error_lib = ../src/libgpg-error.la
 
-TESTS = t-version t-strerror t-syserror t-lock t-printf t-poll
+TESTS = t-version t-strerror t-syserror t-lock t-printf t-poll t-b64dec
 
 AM_CPPFLAGS = -I$(top_builddir)/src $(extra_includes)
 
diff --git a/tests/t-b64dec.c b/tests/t-b64dec.c
new file mode 100644
index 0000000..aae208b
--- /dev/null
+++ b/tests/t-b64dec.c
@@ -0,0 +1,123 @@
+/* t-b64dec.c - b64dec test.
+   Copyright (C) 2017 g10 Code GmbH
+
+   This file is part of libgpg-error.
+
+   libgpg-error is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   libgpg-error is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with libgpgme-error; if not, write to the Free
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <gpg-error.h>
+
+static const char *test_b64_string = "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29"
+  "mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgd"
+  "W5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIEx"
+  "pY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb"
+  "247IGVpdGhlciB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXI"
+  "gb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4=";
+
+static const char *test_string = "libgpg-error is free software; "
+  "you can redistribute it and/or modify it under the terms of "
+  "the GNU Lesser General Public License as published by the Free "
+  "Software Foundation; either version 2.1 of the License, or "
+  "(at your option) any later version.";
+
+#define fail(a)  do { fprintf (stderr, "%s:%d: test %d failed\n",\
+                               __FILE__,__LINE__, (a));          \
+                     errcount++;                                 \
+                   } while(0)
+
+static int errcount;
+
+static gpg_error_t
+test_b64dec_string (const char *string, const char *expected)
+{
+  gpg_error_t err;
+  gpgrt_b64state_t state;
+  char *buffer;
+  size_t len;
+
+  len = strlen (string);
+  buffer = malloc (strlen (string) + 1);
+  if (!buffer)
+    {
+      err = gpg_error_from_syserror ();
+      return err;
+    }
+
+  state = gpgrt_b64dec_start ("");
+  if (!state)
+    {
+      err = gpg_error_from_syserror ();
+      free (buffer);
+      return err;
+    }
+
+  err = gpgrt_b64dec_proc (state, buffer, len, &len);
+  if (err)
+    {
+      if (gpg_err_code (err) != GPG_ERR_EOF)
+        {
+          free (buffer);
+          free (state);
+          return err;
+        }
+    }
+
+  err = gpgrt_b64dec_finish (state);
+  if (err)
+    {
+      free (buffer);
+      return err;
+    }
+
+  if (strncmp (buffer, expected, len) == 0)
+    err = 0;
+  else
+    err = GPG_ERR_INTERNAL;
+
+  free (buffer);
+  return err;
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+  gpg_error_t err;
+
+  (void)argc;
+  (void)argv;
+
+  err = test_b64dec_string (test_b64_string, test_string);
+
+  if (err)
+    {
+      fail (1);
+      return 1;
+    }
+  else
+    return 0;
+}

-----------------------------------------------------------------------

Summary of changes:
 NEWS                 |   7 ++
 src/Makefile.am      |   2 +-
 src/b64dec.c         | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gpg-error.def.in |   4 +
 src/gpg-error.h.in   |  10 ++
 src/gpg-error.vers   |   4 +
 src/gpgrt-int.h      |   6 ++
 src/visibility.c     |  19 ++++
 src/visibility.h     |   7 ++
 tests/Makefile.am    |   2 +-
 tests/t-b64dec.c     | 123 +++++++++++++++++++++++
 11 files changed, 461 insertions(+), 2 deletions(-)
 create mode 100644 src/b64dec.c
 create mode 100644 tests/t-b64dec.c


hooks/post-receive
-- 
Error codes used by GnuPG et al.
http://git.gnupg.org




More information about the Gnupg-commits mailing list