[git] GCRYPT - branch, LIBGCRYPT-1-6-BRANCH, updated. libgcrypt-1.6.0-20-g8ca5966

by Werner Koch cvs at cvs.gnupg.org
Tue Jan 28 16:05:41 CET 2014


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 "The GNU crypto library".

The branch, LIBGCRYPT-1-6-BRANCH has been updated
       via  8ca5966198b4d0d3932978880dc21cb75bf75d56 (commit)
      from  420f42a5752e90a8b27d58ffa1ddfe6e4ab341e8 (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 8ca5966198b4d0d3932978880dc21cb75bf75d56
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jan 9 19:14:09 2014 +0100

    sexp: Fix broken gcry_sexp_nth.
    
    * src/sexp.c (_gcry_sexp_nth): Return a valid S-expression for a data
    element.
    (NODE): Remove unused typedef.
    (ST_HINT): Comment unused macro.
    
    * tests/tsexp.c (bug_1594): New.
    (main): Run new test.
    --
    
    Before 1.6.0 gcry_sexp_nth (list, 0) with a LIST of "(a (b 3:pqr) (c
    3:456) (d 3:xyz))" returned the entire list.  1.6.0 instead returned
    NULL.  However, this is also surprising and the expected value would
    be "(a)".  This patch fixes this.
    
    Somewhat related to that gcry_sexp_nth returned a broken list if
    requesting index 1 of a list like "(n foo)".  It returned just the
    "foo" but not as a list which is required by the S-expression specs.
    Due to this patch the returned value is now "(foo)".
    
    Thanks to Ludovic Courtès for pointing out these problems.
    
    GnuPG-bug-id: 1594
    (cherry picked from commit cbdc355415f83ed62da4f3618767eba54d7e6d37)
    
    Resolved conflicts:
    	tests/tsexp.c: Fix for renamed file in master.

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index c2534a2..58491fb 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4137,8 +4137,9 @@ no such element, @code{NULL} is returned.
 @deftypefun gcry_sexp_t gcry_sexp_car (@w{const gcry_sexp_t @var{list}})
 
 Create and return a new S-expression from the first element in
- at var{list}; this called the "type" and should always exist and be a
-string. @code{NULL} is returned in case of a problem.
+ at var{list}; this is called the "type" and should always exist per
+S-expression specification and in general be a string.  @code{NULL} is
+returned in case of a problem.
 @end deftypefun
 
 @deftypefun gcry_sexp_t gcry_sexp_cdr (@w{const gcry_sexp_t @var{list}})
diff --git a/src/sexp.c b/src/sexp.c
index f31da00..0e4af52 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -1,7 +1,7 @@
 /* sexp.c  -  S-Expression handling
  * Copyright (C) 1999, 2000, 2001, 2002, 2003,
  *               2004, 2006, 2007, 2008, 2011  Free Software Foundation, Inc.
- * Copyright (C) 2013 g10 Code GmbH
+ * Copyright (C) 2013, 2014 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -32,7 +32,55 @@
 #define GCRYPT_NO_MPI_MACROS 1
 #include "g10lib.h"
 
-typedef struct gcry_sexp *NODE;
+
+/* Notes on the internal memory layout.
+
+   We store an S-expression as one memory buffer with tags, length and
+   value.  The simplest list would thus be:
+
+   /----------+----------+---------+------+-----------+----------\
+   | open_tag | data_tag | datalen | data | close_tag | stop_tag |
+   \----------+----------+---------+------+-----------+----------/
+
+   Expressed more compact and with an example:
+
+   /----+----+----+---+----+----\
+   | OT | DT | DL | D | CT | ST |  "(foo)"
+   \----+----+----+---+----+----/
+
+   The open tag must always be the first tag of a list as requires by
+   the S-expression specs.  At least data element (data_tag, datalen,
+   data) is required as well.  The close_tag finishes the list and
+   would actually be sufficient.  For fail-safe reasons a final stop
+   tag is always the last byte in a buffer; it has a value of 0 so
+   that string function accidently applied to an S-expression will
+   never access unallocated data.  We do not support display hints and
+   thus don't need to represent them.  A list may have more an
+   arbitrary number of data elements but at least one is required.
+   The length of each data must be greater than 0 and has a current
+   limit to 65535 bytes (by means of the DATALEN type).
+
+   A list with two data elements:
+
+   /----+----+----+---+----+----+---+----+----\
+   | OT | DT | DL | D | DT | DL | D | CT | ST |  "(foo bar)"
+   \----+----+----+---+----+----+---+----+----/
+
+   In the above example both DL fields have a value of 3.
+   A list of a list with one data element:
+
+   /----+----+----+----+---+----+----+----\
+   | OT | OT | DT | DL | D | CT | CT | ST |  "((foo))"
+   \----+----+----+----+---+----+----+----/
+
+   A list with one element followed by another list:
+
+   /----+----+----+---+----+----+----+---+----+----+----\
+   | OT | DT | DL | D | OT | DT | DL | D | CT | CT | ST |  "(foo (bar))"
+   \----+----+----+---+----+----+----+---+----+----+----/
+
+ */
+
 typedef unsigned short DATALEN;
 
 struct gcry_sexp
@@ -42,11 +90,11 @@ struct gcry_sexp
 
 #define ST_STOP  0
 #define ST_DATA  1  /* datalen follows */
-#define ST_HINT  2  /* datalen follows */
+/*#define ST_HINT  2   datalen follows (currently not used) */
 #define ST_OPEN  3
 #define ST_CLOSE 4
 
-/* the atoi macros assume that the buffer has only valid digits */
+/* The atoi macros assume that the buffer has only valid digits.  */
 #define atoi_1(p)   (*(p) - '0' )
 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
@@ -167,9 +215,10 @@ _gcry_sexp_dump (const gcry_sexp_t a)
     }
 }
 
-/****************
- * Pass list through except when it is an empty list - in that case
- * return NULL and release the passed list.
+
+/* Pass list through except when it is an empty list - in that case
+ * return NULL and release the passed list.  This is used to make sure
+ * that no forbidden empty lists are created.
  */
 static gcry_sexp_t
 normalize ( gcry_sexp_t list )
@@ -501,7 +550,7 @@ _gcry_sexp_length (const gcry_sexp_t list)
 
 
 /* Return the internal lengths offset of LIST.  That is the size of
-   the buffer from the first ST_OPEN, which is retruned at R_OFF, to
+   the buffer from the first ST_OPEN, which is returned at R_OFF, to
    the corresponding ST_CLOSE inclusive.  */
 static size_t
 get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
@@ -542,8 +591,8 @@ get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
 
 
 
-/* Extract the CAR of the given list.  May return NULL for bad lists
-   or memory failure.  */
+/* Extract the n-th element of the given LIST.  Returns NULL for
+   no-such-element, a corrupt list, or memory failure.  */
 gcry_sexp_t
 _gcry_sexp_nth (const gcry_sexp_t list, int number)
 {
@@ -587,15 +636,16 @@ _gcry_sexp_nth (const gcry_sexp_t list, int number)
 
   if (*p == ST_DATA)
     {
-      memcpy (&n, p, sizeof n);
-      p += sizeof n;
-      newlist = xtrymalloc (sizeof *newlist + n + 1);
+      memcpy (&n, p+1, sizeof n);
+      newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
       if (!newlist)
         return NULL;
       d = newlist->d;
-      memcpy (d, p, n);
-      d += n;
-      *d++ = ST_STOP;
+      *d++ = ST_OPEN;
+      memcpy (d, p, 1 + sizeof n + n);
+      d += 1 + sizeof n + n;
+      *d++ = ST_CLOSE;
+      *d = ST_STOP;
     }
   else if (*p == ST_OPEN)
     {
@@ -639,6 +689,7 @@ _gcry_sexp_nth (const gcry_sexp_t list, int number)
   return normalize (newlist);
 }
 
+
 gcry_sexp_t
 _gcry_sexp_car (const gcry_sexp_t list)
 {
diff --git a/tests/tsexp.c b/tests/tsexp.c
index 704f9b1..5a02c26 100644
--- a/tests/tsexp.c
+++ b/tests/tsexp.c
@@ -1043,6 +1043,76 @@ check_extract_param (void)
 }
 
 
+/* A test based on bug 1594.  */
+static void
+bug_1594 (void)
+{
+static char thing[] =
+  "(signature"
+  " (public-key"
+  "  (rsa"
+  "   (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
+  "       6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
+  "       6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
+  "       C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
+  "       CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
+  "       54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
+  "       13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
+  "       A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
+  "       F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
+  "       A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
+  "       E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
+  "       E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
+  "       923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
+  "       EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
+  "       2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
+  "       95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
+  "       67#)"
+  "   (e #010001#))))";
+  gcry_sexp_t sig, pubkey, n, n_val;
+
+  info ("checking fix for bug 1594\n");
+
+  if (gcry_sexp_new (&sig, thing, 0, 1))
+    die ("scanning fixed string failed\n");
+  pubkey = gcry_sexp_find_token (sig, "public-key", 0);
+  gcry_sexp_release (sig);
+  if (!pubkey)
+    {
+      fail ("'public-key' token not found");
+      return;
+    }
+  n = gcry_sexp_find_token (pubkey, "n", 0);
+  if (!n)
+    {
+      fail ("'n' token not found");
+      gcry_sexp_release (pubkey);
+      return;
+    }
+  n_val = gcry_sexp_nth (n, 1);
+  /* Bug 1594 would require the following test:
+   *   if (n_val)
+   *     fail ("extracting 1-th of 'n' list did not fail");
+   * However, we meanwhile modified the S-expression functions to
+   * behave like Scheme to allow the access of any element of a list.
+   */
+  if (!n_val)
+    fail ("extracting 1-th of 'n' list failed");
+  /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)"  */
+  gcry_sexp_release (n_val);
+  n_val = gcry_sexp_nth (n, 2);
+  if (n_val)
+    fail ("extracting 2-th of 'n' list did not fail");
+  n_val = gcry_sexp_nth (n, 0);
+  if (!n_val)
+    fail ("extracting 0-th of 'n' list failed");
+  /*gcry_log_debugsxp ("0-th", n_val); => "(n)"  */
+  if (gcry_sexp_nth (n_val, 1))
+    fail ("extracting 1-th of car of 'n' list did not fail");
+  gcry_sexp_release (n_val);
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -1057,6 +1127,7 @@ main (int argc, char **argv)
   back_and_forth ();
   check_sscan ();
   check_extract_param ();
+  bug_1594 ();
 
   return error_count? 1:0;
 }

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

Summary of changes:
 doc/gcrypt.texi |    5 ++--
 src/sexp.c      |   83 ++++++++++++++++++++++++++++++++++++++++++++-----------
 tests/tsexp.c   |   71 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+), 18 deletions(-)


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org




More information about the Gnupg-commits mailing list