g13: Add functions to handle uint in a keyblob.
authorWerner Koch <wk@gnupg.org>
Wed, 10 Feb 2016 19:44:19 +0000 (20:44 +0100)
committerWerner Koch <wk@gnupg.org>
Sat, 13 Feb 2016 16:06:39 +0000 (17:06 +0100)
* g13/utils.c (append_tuple_uint): New.
(find_tuple_uint): New.
* g13/t-utils.c: New.
* g13/Makefile.am (noinst_PROGRAMS, TESTS): New.
(module_tests, t_common_ldadd): New.
(t_utils_SOURCES, t_utils_LDADD): New.

Signed-off-by: Werner Koch <wk@gnupg.org>
g13/Makefile.am
g13/t-utils.c [new file with mode: 0644]
g13/utils.c
g13/utils.h

index 62437e5..5a2ffb2 100644 (file)
@@ -23,6 +23,9 @@ EXTRA_DIST = ChangeLog-2011
 bin_PROGRAMS = g13
 sbin_PROGRAMS = g13-syshelp
 
+noinst_PROGRAMS = $(module_tests)
+TESTS = $(module_tests)
+
 AM_CPPFLAGS = -I$(top_srcdir)/common
 
 include $(top_srcdir)/am/cmacros.am
@@ -61,3 +64,14 @@ g13_syshelp_SOURCES = \
 g13_syshelp_LDADD = $(libcommon) \
        $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
        $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
+
+
+module_tests = t-utils
+t_common_ldadd = $(libcommon) $(LIBGCRYPT_LIBS) \
+                $(LIBASSUAN_LIBS)
+
+t_utils_SOURCES = t-utils.c utils.c
+t_utils_LDADD = $(t_common_ldadd)
+
+
+$(PROGRAMS) : $(libcommon) $(libcommonpth)
diff --git a/g13/t-utils.c b/g13/t-utils.c
new file mode 100644 (file)
index 0000000..5605216
--- /dev/null
@@ -0,0 +1,223 @@
+/* t-utils.c - Module test for utils.c
+ * Copyright (C) 2016 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+#include "util.h"
+#include "keyblob.h"
+#include "utils.h"
+
+#define PGM "t-utils"
+
+static int verbose;
+static int debug;
+static int errcount;
+
+/* Test for the functions append_tuple_uint and find_tuple_unit.  */
+static void
+test_tuple_uint (void)
+{
+  static struct {
+    int tag;
+    int len;
+    char *data;
+    unsigned long long val;
+    gpg_err_code_t ec;
+  } tv[] = {
+    { 1, 0, "",     0, GPG_ERR_ERANGE },
+    { 2, 1, "\x00", 0, 0},
+    { 3, 1, "\x7f", 127ull, 0},
+    { 4, 1, "\x80", 0, GPG_ERR_ERANGE },
+    { 5, 1, "\x81", 0, GPG_ERR_ERANGE },
+    { 6, 2, "\x80\x01", 0, GPG_ERR_ERANGE },
+    { 7, 2, "\x00\x80", 128ull, 0 },
+    { 8, 1, "\x01", 1, 0 },
+    { 9, 1, "\x40", 64, 0 },
+    { 10, 2, "\x40\x00", 16384, 0 },
+    { 11, 8, "\x7f\xff\xff\xff\xff\xff\xff\xff", 0x7fffffffffffffffull, 0 },
+    { 12, 9, "\x00\xff\xff\xff\xff\xff\xff\xff\xff", 0xffffffffffffffffull, 0},
+    { 13, 9, "\x01\xff\xff\xff\xff\xff\xff\xff\xff", 0, GPG_ERR_ERANGE }
+  };
+  int tidx;
+  gpg_error_t err;
+  membuf_t mb, mb2;
+  void *p;
+  const void *s;
+  size_t n;
+  tupledesc_t tuples;
+  tupledesc_t tuples2;
+  unsigned long long value;
+  int i;
+
+  init_membuf (&mb, 512);
+  init_membuf (&mb2, 512);
+  append_tuple (&mb, KEYBLOB_TAG_BLOBVERSION, "\x01", 1);
+  append_tuple (&mb2, KEYBLOB_TAG_BLOBVERSION, "\x01", 1);
+  for (tidx=0; tidx < DIM (tv); tidx++)
+    {
+      append_tuple (&mb, tv[tidx].tag, tv[tidx].data, tv[tidx].len);
+      if (!tv[tidx].ec)
+        append_tuple_uint (&mb2, tv[tidx].tag, tv[tidx].val);
+    }
+
+  p = get_membuf (&mb, &n);
+  if (!p)
+    {
+      err = gpg_error_from_syserror ();
+      fprintf (stderr, PGM ":%s: get_membuf failed: %s\n",
+               __func__, gpg_strerror (err));
+      exit (1);
+    }
+  err = create_tupledesc (&tuples, p, n);
+  if (err)
+    {
+      fprintf (stderr, PGM ":%s: create_tupledesc failed: %s\n",
+               __func__, gpg_strerror (err));
+      exit (1);
+    }
+  p = get_membuf (&mb2, &n);
+  if (!p)
+    {
+      err = gpg_error_from_syserror ();
+      fprintf (stderr, PGM ":%s: get_membuf failed: %s\n",
+               __func__, gpg_strerror (err));
+      exit (1);
+    }
+  err = create_tupledesc (&tuples2, p, n);
+  if (err)
+    {
+      fprintf (stderr, PGM ":%s: create_tupledesc failed: %s\n",
+               __func__, gpg_strerror (err));
+      exit (1);
+    }
+
+  for (tidx=0; tidx < DIM (tv); tidx++)
+    {
+      err = find_tuple_uint (tuples, tv[tidx].tag, &value);
+      if (tv[tidx].ec != gpg_err_code (err))
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong error returned; "
+                   "expected(%s) got(%s)\n",
+                   __func__, tidx,
+                   gpg_strerror (tv[tidx].ec), gpg_strerror (err));
+          errcount++;
+        }
+      else if (!err && tv[tidx].val != value)
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong value returned; "
+                   "expected(%llx) got(%llx)\n",
+                   __func__, tidx, tv[tidx].val, value);
+          errcount++;
+        }
+
+      err = find_tuple_uint (tuples2, tv[tidx].tag, &value);
+      if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+        {
+          if (!tv[tidx].ec)
+            {
+              fprintf (stderr, PGM ":%s:tidx=%d: find_tuple failed: %s\n",
+                       __func__, tidx, gpg_strerror (err));
+              errcount++;
+            }
+        }
+      else if (tv[tidx].ec != gpg_err_code (err))
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong error returned (2); "
+                   "expected(%s) got(%s)\n",
+                   __func__, tidx,
+                   gpg_strerror (tv[tidx].ec), gpg_strerror (err));
+          errcount++;
+        }
+      else if (!err && tv[tidx].val != value)
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong value returned (2); "
+                   "expected(%llx) got(%llx)\n",
+                   __func__, tidx, tv[tidx].val, value);
+          errcount++;
+        }
+
+      s = find_tuple (tuples2, tv[tidx].tag, &n);
+      if (!s)
+        ;
+      else if (tv[tidx].len != n)
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong string length returned; "
+                   "expected(%d) got(%zu)\n",
+                   __func__, tidx, tv[tidx].len, n);
+          errcount++;
+            }
+      else if (memcmp (tv[tidx].data, s, n))
+        {
+          fprintf (stderr, PGM ":%s:tidx=%d: wrong string returned:",
+                   __func__, tidx);
+          for (i=0; i < n; i++)
+            fprintf (stderr, " %02x", ((unsigned char*)s)[i]);
+          fputc ('\n', stderr);
+          errcount++;
+        }
+    }
+
+  destroy_tupledesc (tuples);
+  destroy_tupledesc (tuples2);
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+
+  gpgrt_init ();
+  if (argc)
+    { argc--; argv++; }
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        {
+          fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+          exit (1);
+        }
+    }
+
+  test_tuple_uint ();
+
+  return !!errcount;
+}
index 4ab4799..dbbaa0d 100644 (file)
@@ -1,5 +1,6 @@
 /* utils.c - Utility functions
  * Copyright (C) 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2009, 2015, 2016  Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -61,10 +62,45 @@ append_tuple (membuf_t *membuf, int tag, const void *value, size_t length)
 }
 
 
+/* Append the unsigned integer VALUE under TAG to MEMBUF.  We make
+ * sure that the most significant bit is always cleared to explicitly
+ * flag the value as unsigned.  */
+void
+append_tuple_uint (membuf_t *membuf, int tag, unsigned long long value)
+{
+  unsigned char buf[16];
+  unsigned char *p;
+  unsigned int len;
+
+  p = buf + sizeof buf;
+  len = 0;
+  do
+    {
+      if (p == buf)
+        BUG () ;
+      *--p = (value & 0xff);
+      value >>= 8;
+      len++;
+    }
+  while (value);
+
+  /* Prepend a zero byte if the first byte has its MSB set.  */
+  if ((*p & 0x80))
+    {
+      if (p == buf)
+        BUG () ;
+      *--p = 0;
+      len++;
+    }
+
+  append_tuple (membuf, tag, p, len);
+}
+
+
 /* Create a tuple object by moving the ownership of (DATA,DATALEN) to
  a new object.  Returns 0 on success and stores the new object at
  R_TUPLEHD.  The return object must be released using
  destroy_tuples().  */
* a new object.  Returns 0 on success and stores the new object at
* R_TUPLEHD.  The return object must be released using
* destroy_tuples().  */
 gpg_error_t
 create_tupledesc (tupledesc_t *r_desc, void *data, size_t datalen)
 {
@@ -108,7 +144,7 @@ ref_tupledesc (tupledesc_t tupledesc)
 
 /* Find the first tuple with tag TAG.  On success return a pointer to
    its value and store the length of the value at R_LENGTH.  If no
-   tuple was return NULL.  For future use by next_tupe, the last
+   tuple was found return NULL.  For use by next_tuple, the last
    position is stored in the descriptor.  */
 const void *
 find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length)
@@ -147,6 +183,43 @@ find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length)
 }
 
 
+/* Similar to find-tuple but expects an unsigned int value and stores
+ * that at R_VALUE.  If the tag was not found GPG_ERR_NOT_FOUND is
+ * returned and 0 stored at R_VALUE.  If the value cannot be converted
+ * to an unsigned integer GPG_ERR_ERANGE is returned.  */
+gpg_error_t
+find_tuple_uint (tupledesc_t tupledesc, unsigned int tag,
+                 unsigned long long *r_value)
+{
+  const unsigned char *s;
+  size_t n;
+  unsigned long long value = 0;
+
+  *r_value = 0;
+
+  s = find_tuple (tupledesc, tag, &n);
+  if (!s)
+    return gpg_error (GPG_ERR_NOT_FOUND);
+  if (!n || (*s & 0x80)) /* No bytes or negative.  */
+    return gpg_error (GPG_ERR_ERANGE);
+  if (n && !*s) /* Skip a leading zero.  */
+    {
+      n--;
+      s++;
+    }
+  if (n > sizeof value)
+    return gpg_error (GPG_ERR_ERANGE);
+  for (; n; n--, s++)
+    {
+      value <<= 8;
+      value |= *s;
+    }
+
+  *r_value = value;
+  return 0;
+}
+
+
 const void *
 next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length)
 {
index 914b2cf..6c3902b 100644 (file)
@@ -25,6 +25,8 @@
 /* Append a new tuple to a memory buffer.  */
 void append_tuple (membuf_t *membuf,
                    int tag, const void *value, size_t length);
+void append_tuple_uint (membuf_t *membuf, int tag,
+                        unsigned long long value);
 
 /* The tuple descriptor object. */
 struct tupledesc_s;
@@ -36,6 +38,8 @@ void destroy_tupledesc (tupledesc_t tupledesc);
 tupledesc_t ref_tupledesc (tupledesc_t tupledesc);
 const void *find_tuple (tupledesc_t tupledesc,
                         unsigned int tag, size_t *r_length);
+gpg_error_t find_tuple_uint (tupledesc_t tupledesc, unsigned int tag,
+                             unsigned long long *r_value);
 const void *next_tuple (tupledesc_t tupledesc,
                         unsigned int *r_tag, size_t *r_length);