LCOV - code coverage report
Current view: top level - src - sexp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 776 1102 70.4 %
Date: 2017-03-02 16:44:37 Functions: 34 41 82.9 %

          Line data    Source code
       1             : /* sexp.c  -  S-Expression handling
       2             :  * Copyright (C) 1999, 2000, 2001, 2002, 2003,
       3             :  *               2004, 2006, 2007, 2008, 2011  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013, 2014 g10 Code GmbH
       5             :  *
       6             :  * This file is part of Libgcrypt.
       7             :  *
       8             :  * Libgcrypt is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU Lesser general Public License as
      10             :  * published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * Libgcrypt is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, write to the Free Software
      20             :  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
      21             :  */
      22             : 
      23             : 
      24             : #include <config.h>
      25             : #include <stdio.h>
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #include <stdarg.h>
      29             : #include <ctype.h>
      30             : #include <errno.h>
      31             : 
      32             : #define GCRYPT_NO_MPI_MACROS 1
      33             : #include "g10lib.h"
      34             : 
      35             : 
      36             : /* Notes on the internal memory layout.
      37             : 
      38             :    We store an S-expression as one memory buffer with tags, length and
      39             :    value.  The simplest list would thus be:
      40             : 
      41             :    /----------+----------+---------+------+-----------+----------\
      42             :    | open_tag | data_tag | datalen | data | close_tag | stop_tag |
      43             :    \----------+----------+---------+------+-----------+----------/
      44             : 
      45             :    Expressed more compact and with an example:
      46             : 
      47             :    /----+----+----+---+----+----\
      48             :    | OT | DT | DL | D | CT | ST |  "(foo)"
      49             :    \----+----+----+---+----+----/
      50             : 
      51             :    The open tag must always be the first tag of a list as requires by
      52             :    the S-expression specs.  At least data element (data_tag, datalen,
      53             :    data) is required as well.  The close_tag finishes the list and
      54             :    would actually be sufficient.  For fail-safe reasons a final stop
      55             :    tag is always the last byte in a buffer; it has a value of 0 so
      56             :    that string function accidentally applied to an S-expression will
      57             :    never access unallocated data.  We do not support display hints and
      58             :    thus don't need to represent them.  A list may have more an
      59             :    arbitrary number of data elements but at least one is required.
      60             :    The length of each data must be greater than 0 and has a current
      61             :    limit to 65535 bytes (by means of the DATALEN type).
      62             : 
      63             :    A list with two data elements:
      64             : 
      65             :    /----+----+----+---+----+----+---+----+----\
      66             :    | OT | DT | DL | D | DT | DL | D | CT | ST |  "(foo bar)"
      67             :    \----+----+----+---+----+----+---+----+----/
      68             : 
      69             :    In the above example both DL fields have a value of 3.
      70             :    A list of a list with one data element:
      71             : 
      72             :    /----+----+----+----+---+----+----+----\
      73             :    | OT | OT | DT | DL | D | CT | CT | ST |  "((foo))"
      74             :    \----+----+----+----+---+----+----+----/
      75             : 
      76             :    A list with one element followed by another list:
      77             : 
      78             :    /----+----+----+---+----+----+----+---+----+----+----\
      79             :    | OT | DT | DL | D | OT | DT | DL | D | CT | CT | ST |  "(foo (bar))"
      80             :    \----+----+----+---+----+----+----+---+----+----+----/
      81             : 
      82             :  */
      83             : 
      84             : typedef unsigned short DATALEN;
      85             : 
      86             : struct gcry_sexp
      87             : {
      88             :   byte d[1];
      89             : };
      90             : 
      91             : #define ST_STOP  0
      92             : #define ST_DATA  1  /* datalen follows */
      93             : /*#define ST_HINT  2   datalen follows (currently not used) */
      94             : #define ST_OPEN  3
      95             : #define ST_CLOSE 4
      96             : 
      97             : /* The atoi macros assume that the buffer has only valid digits.  */
      98             : #define atoi_1(p)   (*(p) - '0' )
      99             : #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
     100             :                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
     101             : #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
     102             : 
     103             : #define TOKEN_SPECIALS  "-./_:*+="
     104             : 
     105             : static gcry_err_code_t
     106             : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
     107             :                 const char *buffer, size_t length, int argflag,
     108             :                 void **arg_list, va_list arg_ptr);
     109             : 
     110             : static gcry_err_code_t
     111             : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
     112             :                const char *buffer, size_t length, int argflag,
     113             :                void **arg_list, ...);
     114             : 
     115             : /* Return true if P points to a byte containing a whitespace according
     116             :    to the S-expressions definition. */
     117             : #undef whitespacep
     118             : static GPG_ERR_INLINE int
     119      255764 : whitespacep (const char *p)
     120             : {
     121      255764 :   switch (*p)
     122             :     {
     123       57995 :     case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
     124      197769 :     default: return 0;
     125             :     }
     126             : }
     127             : 
     128             : 
     129             : #if 0
     130             : static void
     131             : dump_mpi( gcry_mpi_t a )
     132             : {
     133             :     char buffer[1000];
     134             :     size_t n = 1000;
     135             : 
     136             :     if( !a )
     137             :         fputs("[no MPI]", stderr );
     138             :     else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
     139             :         fputs("[MPI too large to print]", stderr );
     140             :     else
     141             :         fputs( buffer, stderr );
     142             : }
     143             : #endif
     144             : 
     145             : static void
     146           0 : dump_string (const byte *p, size_t n, int delim )
     147             : {
     148           0 :   for (; n; n--, p++ )
     149             :     {
     150           0 :       if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
     151             :         {
     152           0 :           if( *p == '\n' )
     153           0 :             log_printf ("\\n");
     154           0 :           else if( *p == '\r' )
     155           0 :             log_printf ("\\r");
     156           0 :           else if( *p == '\f' )
     157           0 :             log_printf ("\\f");
     158           0 :           else if( *p == '\v' )
     159           0 :             log_printf ("\\v");
     160           0 :             else if( *p == '\b' )
     161           0 :               log_printf ("\\b");
     162           0 :           else if( !*p )
     163           0 :             log_printf ("\\0");
     164             :           else
     165           0 :             log_printf ("\\x%02x", *p );
     166             :         }
     167             :       else
     168           0 :         log_printf ("%c", *p);
     169             :     }
     170           0 : }
     171             : 
     172             : 
     173             : void
     174           0 : _gcry_sexp_dump (const gcry_sexp_t a)
     175             : {
     176             :   const byte *p;
     177           0 :   int indent = 0;
     178             :   int type;
     179             : 
     180           0 :   if (!a)
     181             :     {
     182           0 :       log_printf ( "[nil]\n");
     183           0 :       return;
     184             :     }
     185             : 
     186           0 :   p = a->d;
     187           0 :   while ( (type = *p) != ST_STOP )
     188             :     {
     189           0 :       p++;
     190           0 :       switch ( type )
     191             :         {
     192             :         case ST_OPEN:
     193           0 :           log_printf ("%*s[open]\n", 2*indent, "");
     194           0 :           indent++;
     195           0 :           break;
     196             :         case ST_CLOSE:
     197           0 :           if( indent )
     198           0 :             indent--;
     199           0 :           log_printf ("%*s[close]\n", 2*indent, "");
     200           0 :           break;
     201             :         case ST_DATA: {
     202             :           DATALEN n;
     203           0 :           memcpy ( &n, p, sizeof n );
     204           0 :           p += sizeof n;
     205           0 :           log_printf ("%*s[data=\"", 2*indent, "" );
     206           0 :           dump_string (p, n, '\"' );
     207           0 :           log_printf ("\"]\n");
     208           0 :           p += n;
     209             :         }
     210           0 :         break;
     211             :         default:
     212           0 :           log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
     213           0 :           break;
     214             :         }
     215             :     }
     216             : }
     217             : 
     218             : 
     219             : /* Pass list through except when it is an empty list - in that case
     220             :  * return NULL and release the passed list.  This is used to make sure
     221             :  * that no forbidden empty lists are created.
     222             :  */
     223             : static gcry_sexp_t
     224       80799 : normalize ( gcry_sexp_t list )
     225             : {
     226             :   unsigned char *p;
     227             : 
     228       80799 :   if ( !list )
     229           2 :     return NULL;
     230       80797 :   p = list->d;
     231       80797 :   if ( *p == ST_STOP )
     232             :     {
     233             :       /* this is "" */
     234           0 :       sexp_release ( list );
     235           0 :       return NULL;
     236             :     }
     237       80797 :   if ( *p == ST_OPEN && p[1] == ST_CLOSE )
     238             :     {
     239             :       /* this is "()" */
     240           0 :       sexp_release ( list );
     241           0 :       return NULL;
     242             :     }
     243             : 
     244       80797 :   return list;
     245             : }
     246             : 
     247             : /* Create a new S-expression object by reading LENGTH bytes from
     248             :    BUFFER, assuming it is canonical encoded or autodetected encoding
     249             :    when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
     250             :    the buffer is transferred to the newly created object.  FREEFNC
     251             :    should be the freefnc used to release BUFFER; there is no guarantee
     252             :    at which point this function is called; most likey you want to use
     253             :    free() or gcry_free().
     254             : 
     255             :    Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
     256             :    BUFFER points to a valid canonical encoded S-expression.  A LENGTH
     257             :    of 0 and AUTODETECT 1 indicates that buffer points to a
     258             :    null-terminated string.
     259             : 
     260             :    This function returns 0 and and the pointer to the new object in
     261             :    RETSEXP or an error code in which case RETSEXP is set to NULL.  */
     262             : gcry_err_code_t
     263         552 : _gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
     264             :                   int autodetect, void (*freefnc)(void*) )
     265             : {
     266             :   gcry_err_code_t errcode;
     267             :   gcry_sexp_t se;
     268             : 
     269         552 :   if (!retsexp)
     270           0 :     return GPG_ERR_INV_ARG;
     271         552 :   *retsexp = NULL;
     272         552 :   if (autodetect < 0 || autodetect > 1 || !buffer)
     273           0 :     return GPG_ERR_INV_ARG;
     274             : 
     275         552 :   if (!length && !autodetect)
     276             :     { /* What a brave caller to assume that there is really a canonical
     277             :          encoded S-expression in buffer */
     278           0 :       length = _gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
     279           0 :       if (!length)
     280           0 :         return errcode;
     281             :     }
     282         552 :   else if (!length && autodetect)
     283             :     { /* buffer is a string */
     284         181 :       length = strlen ((char *)buffer);
     285             :     }
     286             : 
     287         552 :   errcode = do_sexp_sscan (&se, NULL, buffer, length, 0, NULL);
     288         552 :   if (errcode)
     289           0 :     return errcode;
     290             : 
     291         552 :   *retsexp = se;
     292         552 :   if (freefnc)
     293             :     {
     294             :       /* For now we release the buffer immediately.  As soon as we
     295             :          have changed the internal represenation of S-expression to
     296             :          the canoncial format - which has the advantage of faster
     297             :          parsing - we will use this function as a closure in our
     298             :          GCRYSEXP object and use the BUFFER directly.  */
     299          20 :       freefnc (buffer);
     300             :     }
     301         552 :   return 0;
     302             : }
     303             : 
     304             : /* Same as gcry_sexp_create but don't transfer ownership */
     305             : gcry_err_code_t
     306         522 : _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
     307             :                int autodetect)
     308             : {
     309         522 :   return _gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
     310             : }
     311             : 
     312             : 
     313             : /****************
     314             :  * Release resource of the given SEXP object.
     315             :  */
     316             : void
     317       97559 : _gcry_sexp_release( gcry_sexp_t sexp )
     318             : {
     319       97559 :   if (sexp)
     320             :     {
     321       80797 :       if (_gcry_is_secure (sexp))
     322             :         {
     323             :           /* Extra paranoid wiping. */
     324           2 :           const byte *p = sexp->d;
     325             :           int type;
     326             : 
     327          62 :           while ( (type = *p) != ST_STOP )
     328             :             {
     329          58 :               p++;
     330          58 :               switch ( type )
     331             :                 {
     332             :                 case ST_OPEN:
     333          16 :                   break;
     334             :                 case ST_CLOSE:
     335          16 :                   break;
     336             :                 case ST_DATA:
     337             :                   {
     338             :                     DATALEN n;
     339          26 :                     memcpy ( &n, p, sizeof n );
     340          26 :                     p += sizeof n;
     341          26 :                     p += n;
     342             :                   }
     343          26 :                   break;
     344             :                 default:
     345           0 :                   break;
     346             :                 }
     347             :             }
     348           2 :           wipememory (sexp->d, p - sexp->d);
     349             :         }
     350       80797 :       xfree ( sexp );
     351             :     }
     352       97559 : }
     353             : 
     354             : 
     355             : /****************
     356             :  * Make a pair from lists a and b, don't use a or b later on.
     357             :  * Special behaviour:  If one is a single element list we put the
     358             :  * element straight into the new pair.
     359             :  */
     360             : gcry_sexp_t
     361           0 : _gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
     362             : {
     363             :   (void)a;
     364             :   (void)b;
     365             : 
     366             :   /* NYI: Implementation should be quite easy with our new data
     367             :      representation */
     368           0 :   BUG ();
     369             :   return NULL;
     370             : }
     371             : 
     372             : 
     373             : /****************
     374             :  * Make a list from all items in the array the end of the array is marked
     375             :  * with a NULL.
     376             :  */
     377             : gcry_sexp_t
     378           0 : _gcry_sexp_alist( const gcry_sexp_t *array )
     379             : {
     380             :   (void)array;
     381             : 
     382             :   /* NYI: Implementation should be quite easy with our new data
     383             :      representation. */
     384           0 :   BUG ();
     385             :   return NULL;
     386             : }
     387             : 
     388             : /****************
     389             :  * Make a list from all items, the end of list is indicated by a NULL
     390             :  */
     391             : gcry_sexp_t
     392           0 : _gcry_sexp_vlist( const gcry_sexp_t a, ... )
     393             : {
     394             :   (void)a;
     395             :   /* NYI: Implementation should be quite easy with our new data
     396             :      representation. */
     397           0 :   BUG ();
     398             :   return NULL;
     399             : }
     400             : 
     401             : 
     402             : /****************
     403             :  * Append n to the list a
     404             :  * Returns: a new ist (which maybe a)
     405             :  */
     406             : gcry_sexp_t
     407           0 : _gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
     408             : {
     409             :   (void)a;
     410             :   (void)n;
     411             :   /* NYI: Implementation should be quite easy with our new data
     412             :      representation. */
     413           0 :   BUG ();
     414             :   return NULL;
     415             : }
     416             : 
     417             : gcry_sexp_t
     418           0 : _gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
     419             : {
     420             :   (void)a;
     421             :   (void)n;
     422             :   /* NYI: Implementation should be quite easy with our new data
     423             :      representation. */
     424           0 :   BUG ();
     425             :   return NULL;
     426             : }
     427             : 
     428             : 
     429             : 
     430             : /****************
     431             :  * Locate token in a list. The token must be the car of a sublist.
     432             :  * Returns: A new list with this sublist or NULL if not found.
     433             :  */
     434             : gcry_sexp_t
     435       64620 : _gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
     436             : {
     437             :   const byte *p;
     438             :   DATALEN n;
     439             : 
     440       64620 :   if ( !list )
     441           0 :     return NULL;
     442             : 
     443       64620 :   if ( !toklen )
     444       37065 :     toklen = strlen(tok);
     445             : 
     446       64620 :   p = list->d;
     447      370717 :   while ( *p != ST_STOP )
     448             :     {
     449      296659 :       if ( *p == ST_OPEN && p[1] == ST_DATA )
     450      111387 :         {
     451      166569 :           const byte *head = p;
     452             : 
     453      166569 :           p += 2;
     454      166569 :           memcpy ( &n, p, sizeof n );
     455      166569 :           p += sizeof n;
     456      166569 :           if ( n == toklen && !memcmp( p, tok, toklen ) )
     457             :             { /* found it */
     458             :               gcry_sexp_t newlist;
     459             :               byte *d;
     460       55182 :               int level = 1;
     461             : 
     462             :               /* Look for the end of the list.  */
     463      346838 :               for ( p += n; level; p++ )
     464             :                 {
     465      291656 :                   if ( *p == ST_DATA )
     466             :                     {
     467      134406 :                         memcpy ( &n, ++p, sizeof n );
     468      134406 :                         p += sizeof n + n;
     469      134406 :                         p--; /* Compensate for later increment. */
     470             :                     }
     471      157250 :                   else if ( *p == ST_OPEN )
     472             :                     {
     473       51034 :                       level++;
     474             :                     }
     475      106216 :                   else if ( *p == ST_CLOSE )
     476             :                     {
     477      106216 :                       level--;
     478             :                     }
     479           0 :                   else if ( *p == ST_STOP )
     480             :                     {
     481           0 :                       BUG ();
     482             :                     }
     483             :                 }
     484       55182 :               n = p - head;
     485             : 
     486       55182 :               newlist = xtrymalloc ( sizeof *newlist + n );
     487       55182 :               if (!newlist)
     488             :                 {
     489             :                   /* No way to return an error code, so we can only
     490             :                      return Not Found. */
     491           0 :                   return NULL;
     492             :                 }
     493       55182 :               d = newlist->d;
     494       55182 :               memcpy ( d, head, n ); d += n;
     495       55182 :               *d++ = ST_STOP;
     496       55182 :               return normalize ( newlist );
     497             :             }
     498      111387 :           p += n;
     499             :         }
     500      130090 :       else if ( *p == ST_DATA )
     501             :         {
     502       60043 :           memcpy ( &n, ++p, sizeof n ); p += sizeof n;
     503       60043 :           p += n;
     504             :         }
     505             :       else
     506       70047 :         p++;
     507             :     }
     508        9438 :   return NULL;
     509             : }
     510             : 
     511             : /****************
     512             :  * Return the length of the given list
     513             :  */
     514             : int
     515        6804 : _gcry_sexp_length (const gcry_sexp_t list)
     516             : {
     517             :   const byte *p;
     518             :   DATALEN n;
     519             :   int type;
     520        6804 :   int length = 0;
     521        6804 :   int level = 0;
     522             : 
     523        6804 :   if (!list)
     524           0 :     return 0;
     525             : 
     526        6804 :   p = list->d;
     527       42030 :   while ((type=*p) != ST_STOP)
     528             :     {
     529       28422 :       p++;
     530       28422 :       if (type == ST_DATA)
     531             :         {
     532       14814 :           memcpy (&n, p, sizeof n);
     533       14814 :           p += sizeof n + n;
     534       14814 :           if (level == 1)
     535       14814 :             length++;
     536             :         }
     537       13608 :       else if (type == ST_OPEN)
     538             :         {
     539        6804 :           if (level == 1)
     540           0 :             length++;
     541        6804 :           level++;
     542             :         }
     543        6804 :       else if (type == ST_CLOSE)
     544             :         {
     545        6804 :           level--;
     546             :         }
     547             :     }
     548        6804 :   return length;
     549             : }
     550             : 
     551             : 
     552             : /* Return the internal lengths offset of LIST.  That is the size of
     553             :    the buffer from the first ST_OPEN, which is returned at R_OFF, to
     554             :    the corresponding ST_CLOSE inclusive.  */
     555             : static size_t
     556         160 : get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
     557             : {
     558             :   const unsigned char *p;
     559             :   DATALEN n;
     560             :   int type;
     561         160 :   int level = 0;
     562             : 
     563         160 :   *r_off = 0;
     564         160 :   if (list)
     565             :     {
     566          98 :       p = list->d;
     567         983 :       while ( (type=*p) != ST_STOP )
     568             :         {
     569         885 :           p++;
     570         885 :           if (type == ST_DATA)
     571             :             {
     572         447 :               memcpy (&n, p, sizeof n);
     573         447 :               p += sizeof n + n;
     574             :             }
     575         438 :           else if (type == ST_OPEN)
     576             :             {
     577         219 :               if (!level)
     578          98 :                 *r_off = (p-1) - list->d;
     579         219 :               level++;
     580             :             }
     581         219 :           else if ( type == ST_CLOSE )
     582             :             {
     583         219 :               level--;
     584         219 :               if (!level)
     585          98 :                 return p - list->d;
     586             :             }
     587             :         }
     588             :     }
     589          62 :   return 0; /* Not a proper list.  */
     590             : }
     591             : 
     592             : 
     593             : 
     594             : /* Extract the n-th element of the given LIST.  Returns NULL for
     595             :    no-such-element, a corrupt list, or memory failure.  */
     596             : gcry_sexp_t
     597        9876 : _gcry_sexp_nth (const gcry_sexp_t list, int number)
     598             : {
     599             :   const byte *p;
     600             :   DATALEN n;
     601             :   gcry_sexp_t newlist;
     602             :   byte *d;
     603        9876 :   int level = 0;
     604             : 
     605        9876 :   if (!list || list->d[0] != ST_OPEN)
     606           0 :     return NULL;
     607        9876 :   p = list->d;
     608             : 
     609       34376 :   while (number > 0)
     610             :     {
     611       14624 :       p++;
     612       14624 :       if (*p == ST_DATA)
     613             :         {
     614        9388 :           memcpy (&n, ++p, sizeof n);
     615        9388 :           p += sizeof n + n;
     616        9388 :           p--;
     617        9388 :           if (!level)
     618        4152 :             number--;
     619             :         }
     620        5236 :       else if (*p == ST_OPEN)
     621             :         {
     622        2618 :           level++;
     623             :         }
     624        2618 :       else if (*p == ST_CLOSE)
     625             :         {
     626        2618 :           level--;
     627        2618 :           if ( !level )
     628        2618 :             number--;
     629             :         }
     630           0 :       else if (*p == ST_STOP)
     631             :         {
     632           0 :           return NULL;
     633             :         }
     634             :     }
     635        9876 :   p++;
     636             : 
     637        9876 :   if (*p == ST_DATA)
     638             :     {
     639           2 :       memcpy (&n, p+1, sizeof n);
     640           2 :       newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
     641           2 :       if (!newlist)
     642           0 :         return NULL;
     643           2 :       d = newlist->d;
     644           2 :       *d++ = ST_OPEN;
     645           2 :       memcpy (d, p, 1 + sizeof n + n);
     646           2 :       d += 1 + sizeof n + n;
     647           2 :       *d++ = ST_CLOSE;
     648           2 :       *d = ST_STOP;
     649             :     }
     650        9874 :   else if (*p == ST_OPEN)
     651             :     {
     652        9872 :       const byte *head = p;
     653             : 
     654        9872 :       level = 1;
     655             :       do {
     656      108952 :         p++;
     657      108952 :         if (*p == ST_DATA)
     658             :           {
     659       55130 :             memcpy (&n, ++p, sizeof n);
     660       55130 :             p += sizeof n + n;
     661       55130 :             p--;
     662             :           }
     663       53822 :         else if (*p == ST_OPEN)
     664             :           {
     665       21975 :             level++;
     666             :           }
     667       31847 :         else if (*p == ST_CLOSE)
     668             :           {
     669       31847 :             level--;
     670             :           }
     671           0 :         else if (*p == ST_STOP)
     672             :           {
     673           0 :             BUG ();
     674             :           }
     675      108952 :       } while (level);
     676        9872 :       n = p + 1 - head;
     677             : 
     678        9872 :       newlist = xtrymalloc (sizeof *newlist + n);
     679        9872 :       if (!newlist)
     680           0 :         return NULL;
     681        9872 :       d = newlist->d;
     682        9872 :       memcpy (d, head, n);
     683        9872 :       d += n;
     684        9872 :       *d++ = ST_STOP;
     685             :     }
     686             :   else
     687           2 :     newlist = NULL;
     688             : 
     689        9876 :   return normalize (newlist);
     690             : }
     691             : 
     692             : 
     693             : gcry_sexp_t
     694        5724 : _gcry_sexp_car (const gcry_sexp_t list)
     695             : {
     696        5724 :   return _gcry_sexp_nth (list, 0);
     697             : }
     698             : 
     699             : 
     700             : /* Helper to get data from the car.  The returned value is valid as
     701             :    long as the list is not modified. */
     702             : static const char *
     703       51424 : do_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
     704             : {
     705             :   const byte *p;
     706             :   DATALEN n;
     707       51424 :   int level = 0;
     708             : 
     709       51424 :   *datalen = 0;
     710       51424 :   if ( !list )
     711           0 :     return NULL;
     712             : 
     713       51424 :   p = list->d;
     714       51424 :   if ( *p == ST_OPEN )
     715       51375 :     p++;             /* Yep, a list. */
     716          49 :   else if (number)
     717           0 :     return NULL;     /* Not a list but N > 0 requested. */
     718             : 
     719             :   /* Skip over N elements. */
     720      145115 :   while (number > 0)
     721             :     {
     722       42267 :       if (*p == ST_DATA)
     723             :         {
     724       42267 :           memcpy ( &n, ++p, sizeof n );
     725       42267 :           p += sizeof n + n;
     726       42267 :           p--;
     727       42267 :           if ( !level )
     728       42267 :             number--;
     729             :         }
     730           0 :       else if (*p == ST_OPEN)
     731             :         {
     732           0 :           level++;
     733             :         }
     734           0 :       else if (*p == ST_CLOSE)
     735             :         {
     736           0 :           level--;
     737           0 :           if ( !level )
     738           0 :             number--;
     739             :         }
     740           0 :       else if (*p == ST_STOP)
     741             :         {
     742           0 :           return NULL;
     743             :         }
     744       42267 :       p++;
     745             :     }
     746             : 
     747             :   /* If this is data, return it.  */
     748       51424 :   if (*p == ST_DATA)
     749             :     {
     750       51400 :       memcpy ( &n, ++p, sizeof n );
     751       51400 :       *datalen = n;
     752       51400 :       return (const char*)p + sizeof n;
     753             :     }
     754             : 
     755          24 :   return NULL;
     756             : }
     757             : 
     758             : 
     759             : /* Get data from the car.  The returned value is valid as long as the
     760             :    list is not modified.  */
     761             : const char *
     762       14162 : _gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
     763             : {
     764       14162 :   return do_sexp_nth_data (list, number, datalen);
     765             : }
     766             : 
     767             : 
     768             : /* Get the nth element of a list which needs to be a simple object.
     769             :    The returned value is a malloced buffer and needs to be freed by
     770             :    the caller.  This is basically the same as gcry_sexp_nth_data but
     771             :    with an allocated result. */
     772             : void *
     773        7828 : _gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
     774             : {
     775             :   const char *s;
     776             :   size_t n;
     777             :   char *buf;
     778             : 
     779        7828 :   *rlength = 0;
     780        7828 :   s = do_sexp_nth_data (list, number, &n);
     781        7828 :   if (!s || !n)
     782           6 :     return NULL;
     783        7822 :   buf = xtrymalloc (n);
     784        7822 :   if (!buf)
     785           0 :     return NULL;
     786        7822 :   memcpy (buf, s, n);
     787        7822 :   *rlength = n;
     788        7822 :   return buf;
     789             : }
     790             : 
     791             : 
     792             : /* Get a string from the car.  The returned value is a malloced string
     793             :    and needs to be freed by the caller.  */
     794             : char *
     795       12771 : _gcry_sexp_nth_string (const gcry_sexp_t list, int number)
     796             : {
     797             :   const char *s;
     798             :   size_t n;
     799             :   char *buf;
     800             : 
     801       12771 :   s = do_sexp_nth_data (list, number, &n);
     802       12771 :   if (!s || n < 1 || (n+1) < 1)
     803           0 :     return NULL;
     804       12771 :   buf = xtrymalloc (n+1);
     805       12771 :   if (!buf)
     806           0 :     return NULL;
     807       12771 :   memcpy (buf, s, n);
     808       12771 :   buf[n] = 0;
     809       12771 :   return buf;
     810             : }
     811             : 
     812             : 
     813             : /*
     814             :  * Get a MPI from the car
     815             :  */
     816             : gcry_mpi_t
     817       20166 : _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
     818             : {
     819             :   size_t n;
     820             :   gcry_mpi_t a;
     821             : 
     822       20166 :   if (mpifmt == GCRYMPI_FMT_OPAQUE)
     823             :     {
     824             :       char *p;
     825             : 
     826        3503 :       p = _gcry_sexp_nth_buffer (list, number, &n);
     827        3503 :       if (!p)
     828           0 :         return NULL;
     829             : 
     830        3503 :       a = _gcry_is_secure (list)? _gcry_mpi_snew (0) : _gcry_mpi_new (0);
     831        3503 :       if (a)
     832        3503 :         mpi_set_opaque (a, p, n*8);
     833             :       else
     834           0 :         xfree (p);
     835             :     }
     836             :   else
     837             :     {
     838             :       const char *s;
     839             : 
     840       16663 :       if (!mpifmt)
     841          27 :         mpifmt = GCRYMPI_FMT_STD;
     842             : 
     843       16663 :       s = do_sexp_nth_data (list, number, &n);
     844       16663 :       if (!s)
     845           0 :         return NULL;
     846             : 
     847       16663 :       if (_gcry_mpi_scan (&a, mpifmt, s, n, NULL))
     848           0 :         return NULL;
     849             :     }
     850             : 
     851       20166 :   return a;
     852             : }
     853             : 
     854             : 
     855             : /****************
     856             :  * Get the CDR
     857             :  */
     858             : gcry_sexp_t
     859        5748 : _gcry_sexp_cdr(const gcry_sexp_t list)
     860             : {
     861             :   const byte *p;
     862             :   const byte *head;
     863             :   DATALEN n;
     864             :   gcry_sexp_t newlist;
     865             :   byte *d;
     866        5748 :   int level = 0;
     867        5748 :   int skip = 1;
     868             : 
     869        5748 :   if (!list || list->d[0] != ST_OPEN)
     870           0 :     return NULL;
     871        5748 :   p = list->d;
     872             : 
     873       17244 :   while (skip > 0)
     874             :     {
     875        5748 :       p++;
     876        5748 :       if (*p == ST_DATA)
     877             :         {
     878        5748 :           memcpy ( &n, ++p, sizeof n );
     879        5748 :           p += sizeof n + n;
     880        5748 :           p--;
     881        5748 :           if ( !level )
     882        5748 :             skip--;
     883             :         }
     884           0 :       else if (*p == ST_OPEN)
     885             :         {
     886           0 :           level++;
     887             :         }
     888           0 :       else if (*p == ST_CLOSE)
     889             :         {
     890           0 :           level--;
     891           0 :           if ( !level )
     892           0 :             skip--;
     893             :         }
     894           0 :       else if (*p == ST_STOP)
     895             :         {
     896           0 :           return NULL;
     897             :         }
     898             :     }
     899        5748 :   p++;
     900             : 
     901        5748 :   head = p;
     902        5748 :   level = 0;
     903             :   do {
     904       88692 :     if (*p == ST_DATA)
     905             :       {
     906       41450 :         memcpy ( &n, ++p, sizeof n );
     907       41450 :         p += sizeof n + n;
     908       41450 :         p--;
     909             :       }
     910       47242 :     else if (*p == ST_OPEN)
     911             :       {
     912       23621 :         level++;
     913             :       }
     914       23621 :     else if (*p == ST_CLOSE)
     915             :       {
     916       23621 :         level--;
     917             :       }
     918           0 :     else if (*p == ST_STOP)
     919             :       {
     920           0 :         return NULL;
     921             :       }
     922       88692 :     p++;
     923       88692 :   } while (level);
     924        5748 :   n = p - head;
     925             : 
     926        5748 :   newlist = xtrymalloc (sizeof *newlist + n + 2);
     927        5748 :   if (!newlist)
     928           0 :     return NULL;
     929        5748 :   d = newlist->d;
     930        5748 :   *d++ = ST_OPEN;
     931        5748 :   memcpy (d, head, n);
     932        5748 :   d += n;
     933        5748 :   *d++ = ST_CLOSE;
     934        5748 :   *d++ = ST_STOP;
     935             : 
     936        5748 :   return normalize (newlist);
     937             : }
     938             : 
     939             : 
     940             : gcry_sexp_t
     941        5724 : _gcry_sexp_cadr ( const gcry_sexp_t list )
     942             : {
     943             :   gcry_sexp_t a, b;
     944             : 
     945        5724 :   a = _gcry_sexp_cdr (list);
     946        5724 :   b = _gcry_sexp_car (a);
     947        5724 :   sexp_release (a);
     948        5724 :   return b;
     949             : }
     950             : 
     951             : 
     952             : static GPG_ERR_INLINE int
     953      142004 : hextonibble (int s)
     954             : {
     955      142004 :   if (s >= '0' && s <= '9')
     956       94007 :     return s - '0';
     957       47997 :   else if (s >= 'A' && s <= 'F')
     958       44292 :     return 10 + s - 'A';
     959        3705 :   else if (s >= 'a' && s <= 'f')
     960        3705 :     return 10 + s - 'a';
     961             :   else
     962           0 :     return 0;
     963             : }
     964             : 
     965             : 
     966             : struct make_space_ctx
     967             : {
     968             :   gcry_sexp_t sexp;
     969             :   size_t allocated;
     970             :   byte *pos;
     971             : };
     972             : 
     973             : 
     974             : static gpg_err_code_t
     975      151964 : make_space ( struct make_space_ctx *c, size_t n )
     976             : {
     977      151964 :   size_t used = c->pos - c->sexp->d;
     978             : 
     979      151964 :   if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
     980             :     {
     981             :       gcry_sexp_t newsexp;
     982             :       byte *newhead;
     983             :       size_t newsize;
     984             : 
     985       17987 :       newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
     986       17987 :       if (newsize <= c->allocated)
     987           0 :         return GPG_ERR_TOO_LARGE;
     988       17987 :       newsexp = xtryrealloc ( c->sexp, sizeof *newsexp + newsize - 1);
     989       17987 :       if (!newsexp)
     990           0 :         return gpg_err_code_from_errno (errno);
     991       17987 :       c->allocated = newsize;
     992       17987 :       newhead = newsexp->d;
     993       17987 :       c->pos = newhead + used;
     994       17987 :       c->sexp = newsexp;
     995             :     }
     996      151964 :   return 0;
     997             : }
     998             : 
     999             : 
    1000             : /* Unquote STRING of LENGTH and store it into BUF.  The surrounding
    1001             :    quotes are must already be removed from STRING.  We assume that the
    1002             :    quoted string is syntacillay correct.  */
    1003             : static size_t
    1004        2260 : unquote_string (const char *string, size_t length, unsigned char *buf)
    1005             : {
    1006        2260 :   int esc = 0;
    1007        2260 :   const unsigned char *s = (const unsigned char*)string;
    1008        2260 :   unsigned char *d = buf;
    1009        2260 :   size_t n = length;
    1010             : 
    1011       17952 :   for (; n; n--, s++)
    1012             :     {
    1013       15692 :       if (esc)
    1014             :         {
    1015           4 :           switch (*s)
    1016             :             {
    1017           0 :             case 'b':  *d++ = '\b'; break;
    1018           0 :             case 't':  *d++ = '\t'; break;
    1019           0 :             case 'v':  *d++ = '\v'; break;
    1020           0 :             case 'n':  *d++ = '\n'; break;
    1021           0 :             case 'f':  *d++ = '\f'; break;
    1022           0 :             case 'r':  *d++ = '\r'; break;
    1023           4 :             case '"':  *d++ = '\"'; break;
    1024           0 :             case '\'': *d++ = '\''; break;
    1025           0 :             case '\\': *d++ = '\\'; break;
    1026             : 
    1027             :             case '\r':  /* ignore CR[,LF] */
    1028           0 :               if (n>1 && s[1] == '\n')
    1029             :                 {
    1030           0 :                   s++; n--;
    1031             :                 }
    1032           0 :               break;
    1033             : 
    1034             :             case '\n':  /* ignore LF[,CR] */
    1035           0 :               if (n>1 && s[1] == '\r')
    1036             :                 {
    1037           0 :                   s++; n--;
    1038             :                 }
    1039           0 :               break;
    1040             : 
    1041             :             case 'x': /* hex value */
    1042           0 :               if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
    1043             :                 {
    1044           0 :                   s++; n--;
    1045           0 :                   *d++ = xtoi_2 (s);
    1046           0 :                   s++; n--;
    1047             :                 }
    1048           0 :               break;
    1049             : 
    1050             :             default:
    1051           0 :               if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
    1052             :                 {
    1053           0 :                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
    1054           0 :                   s += 2;
    1055           0 :                   n -= 2;
    1056             :                 }
    1057           0 :               break;
    1058             :             }
    1059           4 :           esc = 0;
    1060             :         }
    1061       15688 :       else if( *s == '\\' )
    1062           4 :         esc = 1;
    1063             :       else
    1064       15684 :         *d++ = *s;
    1065             :     }
    1066             : 
    1067        2260 :   return d - buf;
    1068             : }
    1069             : 
    1070             : /****************
    1071             :  * Scan the provided buffer and return the S expression in our internal
    1072             :  * format.  Returns a newly allocated expression.  If erroff is not NULL and
    1073             :  * a parsing error has occurred, the offset into buffer will be returned.
    1074             :  * If ARGFLAG is true, the function supports some printf like
    1075             :  * expressions.
    1076             :  *  These are:
    1077             :  *      %m - MPI
    1078             :  *      %s - string (no autoswitch to secure allocation)
    1079             :  *      %d - integer stored as string (no autoswitch to secure allocation)
    1080             :  *      %b - memory buffer; this takes _two_ arguments: an integer with the
    1081             :  *           length of the buffer and a pointer to the buffer.
    1082             :  *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
    1083             :  *           regular one, starting with a parenthesis.
    1084             :  *           (no autoswitch to secure allocation)
    1085             :  *  all other format elements are currently not defined and return an error.
    1086             :  *  this includes the "%%" sequence becauce the percent sign is not an
    1087             :  *  allowed character.
    1088             :  * FIXME: We should find a way to store the secure-MPIs not in the string
    1089             :  * but as reference to somewhere - this can help us to save huge amounts
    1090             :  * of secure memory.  The problem is, that if only one element is secure, all
    1091             :  * other elements are automagicaly copied to secure memory too, so the most
    1092             :  * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
    1093             :  * regardless whether it is needed or not.
    1094             :  */
    1095             : static gpg_err_code_t
    1096        9995 : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1097             :                 const char *buffer, size_t length, int argflag,
    1098             :                 void **arg_list, va_list arg_ptr)
    1099             : {
    1100        9995 :   gcry_err_code_t err = 0;
    1101             :   static const char tokenchars[] =
    1102             :     "abcdefghijklmnopqrstuvwxyz"
    1103             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    1104             :     "0123456789-./_:*+=";
    1105             :   const char *p;
    1106             :   size_t n;
    1107        9995 :   const char *digptr = NULL;
    1108        9995 :   const char *quoted = NULL;
    1109        9995 :   const char *tokenp = NULL;
    1110        9995 :   const char *hexfmt = NULL;
    1111        9995 :   const char *base64 = NULL;
    1112        9995 :   const char *disphint = NULL;
    1113        9995 :   const char *percent = NULL;
    1114        9995 :   int hexcount = 0;
    1115        9995 :   int quoted_esc = 0;
    1116        9995 :   int datalen = 0;
    1117             :   size_t dummy_erroff;
    1118             :   struct make_space_ctx c;
    1119        9995 :   int arg_counter = 0;
    1120        9995 :   int level = 0;
    1121             : 
    1122        9995 :   if (!retsexp)
    1123           0 :     return GPG_ERR_INV_ARG;
    1124        9995 :   *retsexp = NULL;
    1125             : 
    1126        9995 :   if (!buffer)
    1127           0 :     return GPG_ERR_INV_ARG;
    1128             : 
    1129        9995 :   if (!erroff)
    1130        9995 :     erroff = &dummy_erroff;
    1131             : 
    1132             :   /* Depending on whether ARG_LIST is non-zero or not, this macro gives
    1133             :      us the next argument, either from the variable argument list as
    1134             :      specified by ARG_PTR or from the argument array ARG_LIST.  */
    1135             : #define ARG_NEXT(storage, type)                          \
    1136             :   do                                                     \
    1137             :     {                                                    \
    1138             :       if (!arg_list)                                     \
    1139             :         storage = va_arg (arg_ptr, type);                \
    1140             :       else                                               \
    1141             :         storage = *((type *) (arg_list[arg_counter++])); \
    1142             :     }                                                    \
    1143             :   while (0)
    1144             : 
    1145             :   /* The MAKE_SPACE macro is used before each store operation to
    1146             :      ensure that the buffer is large enough.  It requires a global
    1147             :      context named C and jumps out to the label LEAVE on error! It
    1148             :      also sets ERROFF using the variables BUFFER and P.  */
    1149             : #define MAKE_SPACE(n)  do {                                                \
    1150             :                             gpg_err_code_t _ms_err = make_space (&c, (n)); \
    1151             :                             if (_ms_err)                                   \
    1152             :                               {                                            \
    1153             :                                 err = _ms_err;                             \
    1154             :                                 *erroff = p - buffer;                      \
    1155             :                                 goto leave;                                \
    1156             :                               }                                            \
    1157             :                        } while (0)
    1158             : 
    1159             :   /* The STORE_LEN macro is used to store the length N at buffer P. */
    1160             : #define STORE_LEN(p,n) do {                                                \
    1161             :                             DATALEN ashort = (n);                          \
    1162             :                             memcpy ( (p), &ashort, sizeof(ashort) );           \
    1163             :                             (p) += sizeof (ashort);                        \
    1164             :                         } while (0)
    1165             : 
    1166             :   /* We assume that the internal representation takes less memory than
    1167             :      the provided one.  However, we add space for one extra datalen so
    1168             :      that the code which does the ST_CLOSE can use MAKE_SPACE */
    1169        9995 :   c.allocated = length + sizeof(DATALEN);
    1170        9995 :   if (length && _gcry_is_secure (buffer))
    1171           0 :     c.sexp = xtrymalloc_secure (sizeof *c.sexp + c.allocated - 1);
    1172             :   else
    1173        9995 :     c.sexp = xtrymalloc (sizeof *c.sexp + c.allocated - 1);
    1174        9995 :   if (!c.sexp)
    1175             :     {
    1176           0 :       err = gpg_err_code_from_errno (errno);
    1177           0 :       *erroff = 0;
    1178           0 :       goto leave;
    1179             :     }
    1180        9995 :   c.pos = c.sexp->d;
    1181             : 
    1182      557396 :   for (p = buffer, n = length; n; p++, n--)
    1183             :     {
    1184      547402 :       if (tokenp && !hexfmt)
    1185             :         {
    1186      223944 :           if (strchr (tokenchars, *p))
    1187      177201 :             continue;
    1188             :           else
    1189             :             {
    1190       46743 :               datalen = p - tokenp;
    1191       46743 :               MAKE_SPACE (datalen);
    1192       46743 :               *c.pos++ = ST_DATA;
    1193       46743 :               STORE_LEN (c.pos, datalen);
    1194       46743 :               memcpy (c.pos, tokenp, datalen);
    1195       46743 :               c.pos += datalen;
    1196       46743 :               tokenp = NULL;
    1197             :             }
    1198             :         }
    1199             : 
    1200      370201 :       if (quoted)
    1201             :         {
    1202       17952 :           if (quoted_esc)
    1203             :             {
    1204           4 :               switch (*p)
    1205             :                 {
    1206             :                 case 'b': case 't': case 'v': case 'n': case 'f':
    1207             :                 case 'r': case '"': case '\'': case '\\':
    1208           4 :                   quoted_esc = 0;
    1209           4 :                   break;
    1210             : 
    1211             :                 case '0': case '1': case '2': case '3': case '4':
    1212             :                 case '5': case '6': case '7':
    1213           0 :                   if (!((n > 2)
    1214           0 :                         && (p[1] >= '0') && (p[1] <= '7')
    1215           0 :                         && (p[2] >= '0') && (p[2] <= '7')))
    1216             :                     {
    1217           0 :                       *erroff = p - buffer;
    1218             :                       /* Invalid octal value.  */
    1219           0 :                       err = GPG_ERR_SEXP_BAD_QUOTATION;
    1220           0 :                       goto leave;
    1221             :                     }
    1222           0 :                   p += 2;
    1223           0 :                   n -= 2;
    1224           0 :                   quoted_esc = 0;
    1225           0 :                   break;
    1226             : 
    1227             :                 case 'x':
    1228           0 :                   if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
    1229             :                     {
    1230           0 :                       *erroff = p - buffer;
    1231             :                       /* Invalid hex value.  */
    1232           0 :                       err = GPG_ERR_SEXP_BAD_QUOTATION;
    1233           0 :                       goto leave;
    1234             :                     }
    1235           0 :                   p += 2;
    1236           0 :                   n -= 2;
    1237           0 :                   quoted_esc = 0;
    1238           0 :                   break;
    1239             : 
    1240             :                 case '\r':
    1241             :                   /* ignore CR[,LF] */
    1242           0 :                   if (n && (p[1] == '\n'))
    1243             :                     {
    1244           0 :                       p++;
    1245           0 :                       n--;
    1246             :                     }
    1247           0 :                   quoted_esc = 0;
    1248           0 :                   break;
    1249             : 
    1250             :                 case '\n':
    1251             :                   /* ignore LF[,CR] */
    1252           0 :                   if (n && (p[1] == '\r'))
    1253             :                     {
    1254           0 :                       p++;
    1255           0 :                       n--;
    1256             :                     }
    1257           0 :                   quoted_esc = 0;
    1258           0 :                   break;
    1259             : 
    1260             :                 default:
    1261           0 :                   *erroff = p - buffer;
    1262             :                   /* Invalid quoted string escape.  */
    1263           0 :                   err = GPG_ERR_SEXP_BAD_QUOTATION;
    1264           0 :                   goto leave;
    1265             :                 }
    1266             :             }
    1267       17948 :           else if (*p == '\\')
    1268           4 :             quoted_esc = 1;
    1269       17944 :           else if (*p == '\"')
    1270             :             {
    1271             :               /* Keep it easy - we know that the unquoted string will
    1272             :                  never be larger. */
    1273             :               unsigned char *save;
    1274             :               size_t len;
    1275             : 
    1276        2260 :               quoted++; /* Skip leading quote.  */
    1277        2260 :               MAKE_SPACE (p - quoted);
    1278        2260 :               *c.pos++ = ST_DATA;
    1279        2260 :               save = c.pos;
    1280        2260 :               STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
    1281        2260 :               len = unquote_string (quoted, p - quoted, c.pos);
    1282        2260 :               c.pos += len;
    1283        2260 :               STORE_LEN (save, len);
    1284        2260 :               quoted = NULL;
    1285             :             }
    1286             :         }
    1287      352249 :       else if (hexfmt)
    1288             :         {
    1289      148780 :           if (isxdigit (*p))
    1290      142004 :             hexcount++;
    1291        6776 :           else if (*p == '#')
    1292             :             {
    1293        1665 :               if ((hexcount & 1))
    1294             :                 {
    1295           0 :                   *erroff = p - buffer;
    1296           0 :                   err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
    1297           0 :                   goto leave;
    1298             :                 }
    1299             : 
    1300        1665 :               datalen = hexcount / 2;
    1301        1665 :               MAKE_SPACE (datalen);
    1302        1665 :               *c.pos++ = ST_DATA;
    1303        1665 :               STORE_LEN (c.pos, datalen);
    1304       77778 :               for (hexfmt++; hexfmt < p; hexfmt++)
    1305             :                 {
    1306             :                   int tmpc;
    1307             : 
    1308       76113 :                   if (whitespacep (hexfmt))
    1309        5111 :                     continue;
    1310       71002 :                   tmpc = hextonibble (*(const unsigned char*)hexfmt);
    1311       71002 :                   for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
    1312             :                     ;
    1313       71002 :                   if (hexfmt < p)
    1314             :                     {
    1315       71002 :                       tmpc *= 16;
    1316       71002 :                       tmpc += hextonibble (*(const unsigned char*)hexfmt);
    1317             :                     }
    1318       71002 :                   *c.pos++ = tmpc;
    1319             :                 }
    1320        1665 :               hexfmt = NULL;
    1321             :             }
    1322        5111 :           else if (!whitespacep (p))
    1323             :             {
    1324           0 :               *erroff = p - buffer;
    1325           0 :               err = GPG_ERR_SEXP_BAD_HEX_CHAR;
    1326           0 :               goto leave;
    1327             :             }
    1328             :         }
    1329      203469 :       else if (base64)
    1330             :         {
    1331           0 :           if (*p == '|')
    1332           0 :             base64 = NULL;
    1333             :         }
    1334      203469 :       else if (digptr)
    1335             :         {
    1336        1826 :           if (digitp (p))
    1337             :             ;
    1338        1462 :           else if (*p == ':')
    1339             :             {
    1340        1462 :               datalen = atoi (digptr); /* FIXME: check for overflow.  */
    1341        1462 :               digptr = NULL;
    1342        1462 :               if (datalen > n - 1)
    1343             :                 {
    1344           0 :                   *erroff = p - buffer;
    1345             :                   /* Buffer too short.  */
    1346           0 :                   err = GPG_ERR_SEXP_STRING_TOO_LONG;
    1347           0 :                   goto leave;
    1348             :                 }
    1349             :               /* Make a new list entry.  */
    1350        1462 :               MAKE_SPACE (datalen);
    1351        1462 :               *c.pos++ = ST_DATA;
    1352        1462 :               STORE_LEN (c.pos, datalen);
    1353        1462 :               memcpy (c.pos, p + 1, datalen);
    1354        1462 :               c.pos += datalen;
    1355        1462 :               n -= datalen;
    1356        1462 :               p += datalen;
    1357             :             }
    1358           0 :           else if (*p == '\"')
    1359             :             {
    1360           0 :               digptr = NULL; /* We ignore the optional length.  */
    1361           0 :               quoted = p;
    1362           0 :               quoted_esc = 0;
    1363             :             }
    1364           0 :           else if (*p == '#')
    1365             :             {
    1366           0 :               digptr = NULL; /* We ignore the optional length.  */
    1367           0 :               hexfmt = p;
    1368           0 :               hexcount = 0;
    1369             :             }
    1370           0 :           else if (*p == '|')
    1371             :             {
    1372           0 :               digptr = NULL; /* We ignore the optional length.  */
    1373           0 :               base64 = p;
    1374             :             }
    1375             :           else
    1376             :             {
    1377           0 :               *erroff = p - buffer;
    1378           0 :               err = GPG_ERR_SEXP_INV_LEN_SPEC;
    1379           0 :               goto leave;
    1380             :             }
    1381             :         }
    1382      201643 :       else if (percent)
    1383             :         {
    1384       11851 :           if (*p == 'm' || *p == 'M')
    1385        3986 :             {
    1386             :               /* Insert an MPI.  */
    1387             :               gcry_mpi_t m;
    1388        3986 :               size_t nm = 0;
    1389        3986 :               int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
    1390             : 
    1391        3986 :               ARG_NEXT (m, gcry_mpi_t);
    1392             : 
    1393        3986 :               if (mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
    1394             :                 {
    1395             :                   void *mp;
    1396             :                   unsigned int nbits;
    1397             : 
    1398        2124 :                   mp = mpi_get_opaque (m, &nbits);
    1399        2124 :                   nm = (nbits+7)/8;
    1400        2124 :                   if (mp && nm)
    1401             :                     {
    1402        2124 :                       MAKE_SPACE (nm);
    1403        2124 :                       if (!_gcry_is_secure (c.sexp->d)
    1404        2124 :                           && mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
    1405             :                         {
    1406             :                           /* We have to switch to secure allocation.  */
    1407             :                           gcry_sexp_t newsexp;
    1408             :                           byte *newhead;
    1409             : 
    1410           0 :                           newsexp = xtrymalloc_secure (sizeof *newsexp
    1411             :                                                        + c.allocated - 1);
    1412           0 :                           if (!newsexp)
    1413             :                             {
    1414           0 :                               err = gpg_err_code_from_errno (errno);
    1415           0 :                               goto leave;
    1416             :                             }
    1417           0 :                           newhead = newsexp->d;
    1418           0 :                           memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1419           0 :                           c.pos = newhead + (c.pos - c.sexp->d);
    1420           0 :                           xfree (c.sexp);
    1421           0 :                           c.sexp = newsexp;
    1422             :                         }
    1423             : 
    1424        2124 :                       *c.pos++ = ST_DATA;
    1425        2124 :                       STORE_LEN (c.pos, nm);
    1426        2124 :                       memcpy (c.pos, mp, nm);
    1427        2124 :                       c.pos += nm;
    1428             :                     }
    1429             :                 }
    1430             :               else
    1431             :                 {
    1432        1862 :                   if (_gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
    1433           0 :                     BUG ();
    1434             : 
    1435        1862 :                   MAKE_SPACE (nm);
    1436        1862 :                   if (!_gcry_is_secure (c.sexp->d)
    1437        1860 :                       && mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
    1438             :                     {
    1439             :                       /* We have to switch to secure allocation.  */
    1440             :                       gcry_sexp_t newsexp;
    1441             :                       byte *newhead;
    1442             : 
    1443         276 :                       newsexp = xtrymalloc_secure (sizeof *newsexp
    1444             :                                                    + c.allocated - 1);
    1445         276 :                       if (!newsexp)
    1446             :                         {
    1447           0 :                           err = gpg_err_code_from_errno (errno);
    1448           0 :                           goto leave;
    1449             :                         }
    1450         276 :                       newhead = newsexp->d;
    1451         276 :                       memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1452         276 :                       c.pos = newhead + (c.pos - c.sexp->d);
    1453         276 :                       xfree (c.sexp);
    1454         276 :                       c.sexp = newsexp;
    1455             :                     }
    1456             : 
    1457        1862 :                   *c.pos++ = ST_DATA;
    1458        1862 :                   STORE_LEN (c.pos, nm);
    1459        1862 :                   if (_gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
    1460           0 :                     BUG ();
    1461        1862 :                   c.pos += nm;
    1462             :                 }
    1463             :             }
    1464        7865 :           else if (*p == 's')
    1465             :             {
    1466             :               /* Insert an string.  */
    1467             :               const char *astr;
    1468             :               size_t alen;
    1469             : 
    1470          98 :               ARG_NEXT (astr, const char *);
    1471          98 :               alen = strlen (astr);
    1472             : 
    1473          98 :               MAKE_SPACE (alen);
    1474          98 :               *c.pos++ = ST_DATA;
    1475          98 :               STORE_LEN (c.pos, alen);
    1476          98 :               memcpy (c.pos, astr, alen);
    1477          98 :               c.pos += alen;
    1478             :             }
    1479        7767 :           else if (*p == 'b')
    1480             :             {
    1481             :               /* Insert a memory buffer.  */
    1482             :               const char *astr;
    1483             :               int alen;
    1484             : 
    1485        7574 :               ARG_NEXT (alen, int);
    1486        7574 :               ARG_NEXT (astr, const char *);
    1487             : 
    1488        7574 :               MAKE_SPACE (alen);
    1489        7574 :               if (alen
    1490        7571 :                   && !_gcry_is_secure (c.sexp->d)
    1491        7571 :                   && _gcry_is_secure (astr))
    1492             :               {
    1493             :                   /* We have to switch to secure allocation.  */
    1494             :                   gcry_sexp_t newsexp;
    1495             :                   byte *newhead;
    1496             : 
    1497           2 :                   newsexp = xtrymalloc_secure (sizeof *newsexp
    1498             :                                                + c.allocated - 1);
    1499           2 :                   if (!newsexp)
    1500             :                     {
    1501           0 :                       err = gpg_err_code_from_errno (errno);
    1502           0 :                       goto leave;
    1503             :                     }
    1504           2 :                   newhead = newsexp->d;
    1505           2 :                   memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1506           2 :                   c.pos = newhead + (c.pos - c.sexp->d);
    1507           2 :                   xfree (c.sexp);
    1508           2 :                   c.sexp = newsexp;
    1509             :                 }
    1510             : 
    1511        7574 :               *c.pos++ = ST_DATA;
    1512        7574 :               STORE_LEN (c.pos, alen);
    1513        7574 :               memcpy (c.pos, astr, alen);
    1514        7574 :               c.pos += alen;
    1515             :             }
    1516         193 :           else if (*p == 'd')
    1517             :             {
    1518             :               /* Insert an integer as string.  */
    1519             :               int aint;
    1520             :               size_t alen;
    1521             :               char buf[35];
    1522             : 
    1523          33 :               ARG_NEXT (aint, int);
    1524          33 :               sprintf (buf, "%d", aint);
    1525          33 :               alen = strlen (buf);
    1526          33 :               MAKE_SPACE (alen);
    1527          33 :               *c.pos++ = ST_DATA;
    1528          33 :               STORE_LEN (c.pos, alen);
    1529          33 :               memcpy (c.pos, buf, alen);
    1530          33 :               c.pos += alen;
    1531             :             }
    1532         160 :           else if (*p == 'u')
    1533             :             {
    1534             :               /* Insert an unsigned integer as string.  */
    1535             :               unsigned int aint;
    1536             :               size_t alen;
    1537             :               char buf[35];
    1538             : 
    1539           0 :               ARG_NEXT (aint, unsigned int);
    1540           0 :               sprintf (buf, "%u", aint);
    1541           0 :               alen = strlen (buf);
    1542           0 :               MAKE_SPACE (alen);
    1543           0 :               *c.pos++ = ST_DATA;
    1544           0 :               STORE_LEN (c.pos, alen);
    1545           0 :               memcpy (c.pos, buf, alen);
    1546           0 :               c.pos += alen;
    1547             :             }
    1548         160 :           else if (*p == 'S')
    1549             :             {
    1550             :               /* Insert a gcry_sexp_t.  */
    1551             :               gcry_sexp_t asexp;
    1552             :               size_t alen, aoff;
    1553             : 
    1554         160 :               ARG_NEXT (asexp, gcry_sexp_t);
    1555         160 :               alen = get_internal_buffer (asexp, &aoff);
    1556         160 :               if (alen)
    1557             :                 {
    1558          98 :                   MAKE_SPACE (alen);
    1559          98 :                   memcpy (c.pos, asexp->d + aoff, alen);
    1560          98 :                   c.pos += alen;
    1561             :                 }
    1562             :             }
    1563             :           else
    1564             :             {
    1565           0 :               *erroff = p - buffer;
    1566             :               /* Invalid format specifier.  */
    1567           0 :               err = GPG_ERR_SEXP_INV_LEN_SPEC;
    1568           0 :               goto leave;
    1569             :             }
    1570       11851 :           percent = NULL;
    1571             :         }
    1572      189792 :       else if (*p == '(')
    1573             :         {
    1574       39026 :           if (disphint)
    1575             :             {
    1576           0 :               *erroff = p - buffer;
    1577             :               /* Open display hint.  */
    1578           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1579           0 :               goto leave;
    1580             :             }
    1581       39026 :           MAKE_SPACE (0);
    1582       39026 :           *c.pos++ = ST_OPEN;
    1583       39026 :           level++;
    1584             :         }
    1585      150766 :       else if (*p == ')')
    1586             :         {
    1587             :           /* Walk up.  */
    1588       39026 :           if (disphint)
    1589             :             {
    1590           0 :               *erroff = p - buffer;
    1591             :               /* Open display hint.  */
    1592           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1593           0 :               goto leave;
    1594             :             }
    1595             : 
    1596       39026 :           if (level == 0)
    1597             :             {
    1598           1 :               *erroff = p - buffer;
    1599           1 :               err = GPG_ERR_SEXP_UNMATCHED_PAREN;
    1600           1 :               goto leave;
    1601             :             }
    1602       39025 :           MAKE_SPACE (0);
    1603       39025 :           *c.pos++ = ST_CLOSE;
    1604       39025 :           level--;
    1605             :         }
    1606      111740 :       else if (*p == '\"')
    1607             :         {
    1608        2260 :           quoted = p;
    1609        2260 :           quoted_esc = 0;
    1610             :         }
    1611      109480 :       else if (*p == '#')
    1612             :         {
    1613        1665 :           hexfmt = p;
    1614        1665 :           hexcount = 0;
    1615             :         }
    1616      107815 :       else if (*p == '|')
    1617           0 :         base64 = p;
    1618      107815 :       else if (*p == '[')
    1619             :         {
    1620           0 :           if (disphint)
    1621             :             {
    1622           0 :               *erroff = p - buffer;
    1623             :               /* Open display hint.  */
    1624           0 :               err = GPG_ERR_SEXP_NESTED_DH;
    1625           0 :               goto leave;
    1626             :             }
    1627           0 :           disphint = p;
    1628             :         }
    1629      107815 :       else if (*p == ']')
    1630             :         {
    1631           0 :           if (!disphint)
    1632             :             {
    1633           0 :               *erroff = p - buffer;
    1634             :               /* Open display hint.  */
    1635           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1636           0 :               goto leave;
    1637             :             }
    1638           0 :           disphint = NULL;
    1639             :         }
    1640      107815 :       else if (digitp (p))
    1641             :         {
    1642        1462 :           if (*p == '0')
    1643             :             {
    1644             :               /* A length may not begin with zero.  */
    1645           0 :               *erroff = p - buffer;
    1646           0 :               err = GPG_ERR_SEXP_ZERO_PREFIX;
    1647           0 :               goto leave;
    1648             :             }
    1649        1462 :           digptr = p;
    1650             :         }
    1651      106353 :       else if (strchr (tokenchars, *p))
    1652       46743 :         tokenp = p;
    1653       59610 :       else if (whitespacep (p))
    1654             :         ;
    1655       11851 :       else if (*p == '{')
    1656             :         {
    1657             :           /* fixme: handle rescanning: we can do this by saving our
    1658             :              current state and start over at p+1 -- Hmmm. At this
    1659             :              point here we are in a well defined state, so we don't
    1660             :              need to save it.  Great.  */
    1661           0 :           *erroff = p - buffer;
    1662           0 :           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    1663           0 :           goto leave;
    1664             :         }
    1665       11851 :       else if (strchr ("&\\", *p))
    1666             :         {
    1667             :           /* Reserved punctuation.  */
    1668           0 :           *erroff = p - buffer;
    1669           0 :           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    1670           0 :           goto leave;
    1671             :         }
    1672       11851 :       else if (argflag && (*p == '%'))
    1673       11851 :         percent = p;
    1674             :       else
    1675             :         {
    1676             :           /* Bad or unavailable.  */
    1677           0 :           *erroff = p - buffer;
    1678           0 :           err = GPG_ERR_SEXP_BAD_CHARACTER;
    1679           0 :           goto leave;
    1680             :         }
    1681             :     }
    1682        9994 :   MAKE_SPACE (0);
    1683        9994 :   *c.pos++ = ST_STOP;
    1684             : 
    1685        9994 :   if (level && !err)
    1686           1 :     err = GPG_ERR_SEXP_UNMATCHED_PAREN;
    1687             : 
    1688             :  leave:
    1689        9995 :   if (err)
    1690             :     {
    1691             :       /* Error -> deallocate.  */
    1692           2 :       if (c.sexp)
    1693             :         {
    1694             :           /* Extra paranoid wipe on error. */
    1695           2 :           if (_gcry_is_secure (c.sexp))
    1696           0 :             wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
    1697           2 :           xfree (c.sexp);
    1698             :         }
    1699             :     }
    1700             :   else
    1701        9993 :     *retsexp = normalize (c.sexp);
    1702             : 
    1703        9995 :   return err;
    1704             : #undef MAKE_SPACE
    1705             : #undef STORE_LEN
    1706             : }
    1707             : 
    1708             : 
    1709             : static gpg_err_code_t
    1710        1481 : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1711             :                const char *buffer, size_t length, int argflag,
    1712             :                void **arg_list, ...)
    1713             : {
    1714             :   gcry_err_code_t rc;
    1715             :   va_list arg_ptr;
    1716             : 
    1717        1481 :   va_start (arg_ptr, arg_list);
    1718        1481 :   rc = do_vsexp_sscan (retsexp, erroff, buffer, length, argflag,
    1719             :                        arg_list, arg_ptr);
    1720        1481 :   va_end (arg_ptr);
    1721             : 
    1722        1481 :   return rc;
    1723             : }
    1724             : 
    1725             : 
    1726             : gpg_err_code_t
    1727        3340 : _gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
    1728             : {
    1729             :   gcry_err_code_t rc;
    1730             :   va_list arg_ptr;
    1731             : 
    1732        3340 :   va_start (arg_ptr, format);
    1733        3340 :   rc = do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
    1734             :                        NULL, arg_ptr);
    1735        3340 :   va_end (arg_ptr);
    1736             : 
    1737        3340 :   return rc;
    1738             : }
    1739             : 
    1740             : 
    1741             : gcry_err_code_t
    1742        5174 : _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
    1743             :                    const char *format, va_list arg_ptr)
    1744             : {
    1745        5174 :   return do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
    1746             :                          NULL, arg_ptr);
    1747             : }
    1748             : 
    1749             : 
    1750             : /* Like gcry_sexp_build, but uses an array instead of variable
    1751             :    function arguments.  */
    1752             : gcry_err_code_t
    1753          34 : _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
    1754             :                         const char *format, void **arg_list)
    1755             : {
    1756          34 :   return do_sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
    1757             : }
    1758             : 
    1759             : 
    1760             : gcry_err_code_t
    1761         895 : _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1762             :                   const char *buffer, size_t length)
    1763             : {
    1764         895 :   return do_sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
    1765             : }
    1766             : 
    1767             : 
    1768             : /* Figure out a suitable encoding for BUFFER of LENGTH.
    1769             :    Returns: 0 = Binary
    1770             :             1 = String possible
    1771             :             2 = Token possible
    1772             : */
    1773             : static int
    1774          94 : suitable_encoding (const unsigned char *buffer, size_t length)
    1775             : {
    1776             :   const unsigned char *s;
    1777          94 :   int maybe_token = 1;
    1778             : 
    1779          94 :   if (!length)
    1780           0 :     return 1;
    1781             : 
    1782          94 :   if (*buffer & 0x80)
    1783          12 :     return 0; /* If the MSB is set we assume that buffer represents a
    1784             :                  negative number.  */
    1785          82 :   if (!*buffer)
    1786           2 :     return 0; /* Starting with a zero is pretty much a binary string.  */
    1787             : 
    1788         470 :   for (s=buffer; length; s++, length--)
    1789             :     {
    1790         392 :       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
    1791           2 :            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
    1792           2 :         return 0; /*binary*/
    1793         390 :       if ( maybe_token
    1794         324 :            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
    1795          26 :         maybe_token = 0;
    1796             :     }
    1797          78 :   s = buffer;
    1798          78 :   if ( maybe_token && !digitp (s) )
    1799          36 :     return 2;
    1800          42 :   return 1;
    1801             : }
    1802             : 
    1803             : 
    1804             : static int
    1805          24 : convert_to_hex (const unsigned char *src, size_t len, char *dest)
    1806             : {
    1807             :   int i;
    1808             : 
    1809          24 :   if (dest)
    1810             :     {
    1811           8 :       *dest++ = '#';
    1812         588 :       for (i=0; i < len; i++, dest += 2 )
    1813         580 :         sprintf (dest, "%02X", src[i]);
    1814           8 :       *dest++ = '#';
    1815             :     }
    1816          24 :   return len*2+2;
    1817             : }
    1818             : 
    1819             : static int
    1820          63 : convert_to_string (const unsigned char *s, size_t len, char *dest)
    1821             : {
    1822          63 :   if (dest)
    1823             :     {
    1824          21 :       char *p = dest;
    1825          21 :       *p++ = '\"';
    1826         108 :       for (; len; len--, s++ )
    1827             :         {
    1828          87 :           switch (*s)
    1829             :             {
    1830           0 :             case '\b': *p++ = '\\'; *p++ = 'b';  break;
    1831           0 :             case '\t': *p++ = '\\'; *p++ = 't';  break;
    1832           0 :             case '\v': *p++ = '\\'; *p++ = 'v';  break;
    1833           0 :             case '\n': *p++ = '\\'; *p++ = 'n';  break;
    1834           0 :             case '\f': *p++ = '\\'; *p++ = 'f';  break;
    1835           0 :             case '\r': *p++ = '\\'; *p++ = 'r';  break;
    1836           3 :             case '\"': *p++ = '\\'; *p++ = '\"';  break;
    1837           0 :             case '\'': *p++ = '\\'; *p++ = '\'';  break;
    1838           0 :             case '\\': *p++ = '\\'; *p++ = '\\';  break;
    1839             :             default:
    1840          84 :               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
    1841             :                 {
    1842           0 :                   sprintf (p, "\\x%02x", *s);
    1843           0 :                   p += 4;
    1844             :                 }
    1845             :               else
    1846          84 :                 *p++ = *s;
    1847             :             }
    1848             :         }
    1849          21 :       *p++ = '\"';
    1850          21 :       return p - dest;
    1851             :     }
    1852             :   else
    1853             :     {
    1854          42 :       int count = 2;
    1855         216 :       for (; len; len--, s++ )
    1856             :         {
    1857         174 :           switch (*s)
    1858             :             {
    1859             :             case '\b':
    1860             :             case '\t':
    1861             :             case '\v':
    1862             :             case '\n':
    1863             :             case '\f':
    1864             :             case '\r':
    1865             :             case '\"':
    1866             :             case '\'':
    1867           6 :             case '\\': count += 2; break;
    1868             :             default:
    1869         168 :               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
    1870           0 :                 count += 4;
    1871             :               else
    1872         168 :                 count++;
    1873             :             }
    1874             :         }
    1875          42 :       return count;
    1876             :     }
    1877             : }
    1878             : 
    1879             : 
    1880             : 
    1881             : static int
    1882          54 : convert_to_token (const unsigned char *src, size_t len, char *dest)
    1883             : {
    1884          54 :   if (dest)
    1885          18 :     memcpy (dest, src, len);
    1886          54 :   return len;
    1887             : }
    1888             : 
    1889             : 
    1890             : /****************
    1891             :  * Print SEXP to buffer using the MODE.  Returns the length of the
    1892             :  * SEXP in buffer or 0 if the buffer is too short (We have at least an
    1893             :  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
    1894             :  * the required length is returned.
    1895             :  */
    1896             : size_t
    1897         750 : _gcry_sexp_sprint (const gcry_sexp_t list, int mode,
    1898             :                    void *buffer, size_t maxlength )
    1899             : {
    1900             :   static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
    1901             :   const unsigned char *s;
    1902             :   char *d;
    1903             :   DATALEN n;
    1904             :   char numbuf[20];
    1905         750 :   size_t len = 0;
    1906         750 :   int i, indent = 0;
    1907             : 
    1908         750 :   s = list? list->d : empty;
    1909         750 :   d = buffer;
    1910        7887 :   while ( *s != ST_STOP )
    1911             :     {
    1912        6387 :       switch ( *s )
    1913             :         {
    1914             :         case ST_OPEN:
    1915        1765 :           s++;
    1916        1765 :           if ( mode != GCRYSEXP_FMT_CANON )
    1917             :             {
    1918          46 :               if (indent)
    1919          26 :                 len++;
    1920          46 :               len += indent;
    1921             :             }
    1922        1765 :           len++;
    1923        1765 :           if ( buffer )
    1924             :             {
    1925         894 :               if ( len >= maxlength )
    1926           0 :                 return 0;
    1927         894 :               if ( mode != GCRYSEXP_FMT_CANON )
    1928             :                 {
    1929          23 :                   if (indent)
    1930          13 :                     *d++ = '\n';
    1931          44 :                   for (i=0; i < indent; i++)
    1932          21 :                     *d++ = ' ';
    1933             :                 }
    1934         894 :               *d++ = '(';
    1935             :             }
    1936        1765 :           indent++;
    1937        1765 :           break;
    1938             :         case ST_CLOSE:
    1939        1765 :           s++;
    1940        1765 :           len++;
    1941        1765 :           if ( buffer )
    1942             :             {
    1943         894 :               if ( len >= maxlength )
    1944           0 :                 return 0;
    1945         894 :               *d++ = ')';
    1946             :             }
    1947        1765 :           indent--;
    1948        1765 :           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
    1949             :             {
    1950          22 :               len++;
    1951          22 :               len += indent;
    1952          22 :               if (buffer)
    1953             :                 {
    1954          11 :                   if (len >= maxlength)
    1955           0 :                     return 0;
    1956          11 :                   *d++ = '\n';
    1957          28 :                   for (i=0; i < indent; i++)
    1958          17 :                     *d++ = ' ';
    1959             :                 }
    1960             :             }
    1961        1765 :           break;
    1962             :         case ST_DATA:
    1963        2857 :           s++;
    1964        2857 :           memcpy ( &n, s, sizeof n ); s += sizeof n;
    1965        2857 :           if (mode == GCRYSEXP_FMT_ADVANCED)
    1966             :             {
    1967             :               int type;
    1968             :               size_t nn;
    1969             : 
    1970          94 :               switch ( (type=suitable_encoding (s, n)))
    1971             :                 {
    1972          42 :                 case 1: nn = convert_to_string (s, n, NULL); break;
    1973          36 :                 case 2: nn = convert_to_token (s, n, NULL); break;
    1974          16 :                 default: nn = convert_to_hex (s, n, NULL); break;
    1975             :                 }
    1976          94 :               len += nn;
    1977          94 :               if (buffer)
    1978             :                 {
    1979          47 :                   if (len >= maxlength)
    1980           0 :                     return 0;
    1981          47 :                   switch (type)
    1982             :                     {
    1983          21 :                     case 1: convert_to_string (s, n, d); break;
    1984          18 :                     case 2: convert_to_token (s, n, d); break;
    1985           8 :                     default: convert_to_hex (s, n, d); break;
    1986             :                     }
    1987          47 :                   d += nn;
    1988             :                 }
    1989          94 :               if (s[n] != ST_CLOSE)
    1990             :                 {
    1991          52 :                   len++;
    1992          52 :                   if (buffer)
    1993             :                     {
    1994          26 :                       if (len >= maxlength)
    1995           0 :                         return 0;
    1996          26 :                       *d++ = ' ';
    1997             :                     }
    1998             :                 }
    1999             :             }
    2000             :           else
    2001             :             {
    2002        2763 :               sprintf (numbuf, "%u:", (unsigned int)n );
    2003        2763 :               len += strlen (numbuf) + n;
    2004        2763 :               if ( buffer )
    2005             :                 {
    2006        1405 :                   if ( len >= maxlength )
    2007           0 :                     return 0;
    2008        1405 :                   d = stpcpy ( d, numbuf );
    2009        1405 :                   memcpy ( d, s, n ); d += n;
    2010             :                 }
    2011             :             }
    2012        2857 :           s += n;
    2013        2857 :           break;
    2014             :         default:
    2015           0 :           BUG ();
    2016             :         }
    2017             :     }
    2018         750 :   if ( mode != GCRYSEXP_FMT_CANON )
    2019             :     {
    2020          20 :       len++;
    2021          20 :       if (buffer)
    2022             :         {
    2023          10 :           if ( len >= maxlength )
    2024           0 :             return 0;
    2025          10 :           *d++ = '\n';
    2026             :         }
    2027             :     }
    2028         750 :   if (buffer)
    2029             :     {
    2030         380 :       if ( len >= maxlength )
    2031           0 :         return 0;
    2032         380 :       *d++ = 0; /* for convenience we make a C string */
    2033             :     }
    2034             :   else
    2035         370 :     len++; /* we need one byte more for this */
    2036             : 
    2037         750 :   return len;
    2038             : }
    2039             : 
    2040             : 
    2041             : /* Scan a canonical encoded buffer with implicit length values and
    2042             :    return the actual length this S-expression uses.  For a valid S-Exp
    2043             :    it should never return 0.  If LENGTH is not zero, the maximum
    2044             :    length to scan is given - this can be used for syntax checks of
    2045             :    data passed from outside. errorcode and erroff may both be passed as
    2046             :    NULL.  */
    2047             : size_t
    2048          14 : _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
    2049             :                       size_t *erroff, gcry_err_code_t *errcode)
    2050             : {
    2051             :   const unsigned char *p;
    2052          14 :   const unsigned char *disphint = NULL;
    2053          14 :   unsigned int datalen = 0;
    2054             :   size_t dummy_erroff;
    2055             :   gcry_err_code_t dummy_errcode;
    2056          14 :   size_t count = 0;
    2057          14 :   int level = 0;
    2058             : 
    2059          14 :   if (!erroff)
    2060           0 :     erroff = &dummy_erroff;
    2061          14 :   if (!errcode)
    2062           0 :     errcode = &dummy_errcode;
    2063             : 
    2064          14 :   *errcode = GPG_ERR_NO_ERROR;
    2065          14 :   *erroff = 0;
    2066          14 :   if (!buffer)
    2067           0 :     return 0;
    2068          14 :   if (*buffer != '(')
    2069             :     {
    2070           1 :       *errcode = GPG_ERR_SEXP_NOT_CANONICAL;
    2071           1 :       return 0;
    2072             :     }
    2073             : 
    2074          48 :   for (p=buffer; ; p++, count++ )
    2075             :     {
    2076          83 :       if (length && count >= length)
    2077             :         {
    2078           3 :           *erroff = count;
    2079           3 :           *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
    2080           3 :           return 0;
    2081             :         }
    2082             : 
    2083          45 :       if (datalen)
    2084             :         {
    2085           9 :           if (*p == ':')
    2086             :             {
    2087           7 :               if (length && (count+datalen) >= length)
    2088             :                 {
    2089           0 :                   *erroff = count;
    2090           0 :                   *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
    2091           0 :                   return 0;
    2092             :                 }
    2093           7 :               count += datalen;
    2094           7 :               p += datalen;
    2095           7 :               datalen = 0;
    2096             :             }
    2097           2 :           else if (digitp(p))
    2098           2 :             datalen = datalen*10 + atoi_1(p);
    2099             :           else
    2100             :             {
    2101           0 :               *erroff = count;
    2102           0 :               *errcode = GPG_ERR_SEXP_INV_LEN_SPEC;
    2103           0 :               return 0;
    2104             :             }
    2105             :         }
    2106          36 :       else if (*p == '(')
    2107             :         {
    2108          16 :           if (disphint)
    2109             :             {
    2110           0 :               *erroff = count;
    2111           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2112           0 :               return 0;
    2113             :             }
    2114          16 :           level++;
    2115             :         }
    2116          20 :       else if (*p == ')')
    2117             :         { /* walk up */
    2118          10 :           if (!level)
    2119             :             {
    2120           0 :               *erroff = count;
    2121           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN;
    2122           0 :               return 0;
    2123             :             }
    2124          10 :           if (disphint)
    2125             :             {
    2126           0 :               *erroff = count;
    2127           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2128           0 :               return 0;
    2129             :             }
    2130          10 :           if (!--level)
    2131           7 :             return ++count; /* ready */
    2132             :         }
    2133          10 :       else if (*p == '[')
    2134             :         {
    2135           0 :           if (disphint)
    2136             :             {
    2137           0 :               *erroff = count;
    2138           0 :               *errcode = GPG_ERR_SEXP_NESTED_DH;
    2139           0 :               return 0;
    2140             :             }
    2141           0 :           disphint = p;
    2142             :         }
    2143          10 :       else if (*p == ']')
    2144             :         {
    2145           0 :           if ( !disphint )
    2146             :             {
    2147           0 :               *erroff = count;
    2148           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2149           0 :               return 0;
    2150             :             }
    2151           0 :           disphint = NULL;
    2152             :         }
    2153          10 :       else if (digitp (p) )
    2154             :         {
    2155           8 :           if (*p == '0')
    2156             :             {
    2157           1 :               *erroff = count;
    2158           1 :               *errcode = GPG_ERR_SEXP_ZERO_PREFIX;
    2159           1 :               return 0;
    2160             :             }
    2161           7 :           datalen = atoi_1 (p);
    2162             :         }
    2163           2 :       else if (*p == '&' || *p == '\\')
    2164             :         {
    2165           0 :           *erroff = count;
    2166           0 :           *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    2167           0 :           return 0;
    2168             :         }
    2169             :       else
    2170             :         {
    2171           2 :           *erroff = count;
    2172           2 :           *errcode = GPG_ERR_SEXP_BAD_CHARACTER;
    2173           2 :           return 0;
    2174             :         }
    2175             :     }
    2176             : }
    2177             : 
    2178             : 
    2179             : /* Extract MPIs from an s-expression using a list of parameters.  The
    2180             :  * names of these parameters are given by the string LIST.  Some
    2181             :  * special characters may be given to control the conversion:
    2182             :  *
    2183             :  *    + :: Switch to unsigned integer format (default).
    2184             :  *    - :: Switch to standard signed format.
    2185             :  *    / :: Switch to opaque format.
    2186             :  *    & :: Switch to buffer descriptor mode - see below.
    2187             :  *    ? :: The previous parameter is optional.
    2188             :  *
    2189             :  * In general parameter names are single letters.  To use a string for
    2190             :  * a parameter name, enclose the name in single quotes.
    2191             :  *
    2192             :  * Unless in gcry_buffer_t mode for each parameter name a pointer to
    2193             :  * an MPI variable is expected that must be set to NULL prior to
    2194             :  * invoking this function, and finally a NULL is expected.  Example:
    2195             :  *
    2196             :  *   _gcry_sexp_extract_param (key, NULL, "n/x+ed",
    2197             :  *                             &mpi_n, &mpi_x, &mpi_e, NULL)
    2198             :  *
    2199             :  * This stores the parameter "N" from KEY as an unsigned MPI into
    2200             :  * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
    2201             :  * parameter "E" again as an unsigned MPI into MPI_E.
    2202             :  *
    2203             :  * If in buffer descriptor mode a pointer to gcry_buffer_t descriptor
    2204             :  * is expected instead of a pointer to an MPI.  The caller may use two
    2205             :  * different operation modes: If the DATA field of the provided buffer
    2206             :  * descriptor is NULL, the function allocates a new buffer and stores
    2207             :  * it at DATA; the other fields are set accordingly with OFF being 0.
    2208             :  * If DATA is not NULL, the function assumes that DATA, SIZE, and OFF
    2209             :  * describe a buffer where to but the data; on return the LEN field
    2210             :  * receives the number of bytes copied to that buffer; if the buffer
    2211             :  * is too small, the function immediately returns with an error code
    2212             :  * (and LEN set to 0).
    2213             :  *
    2214             :  * PATH is an optional string used to locate a token.  The exclamation
    2215             :  * mark separated tokens are used to via gcry_sexp_find_token to find
    2216             :  * a start point inside SEXP.
    2217             :  *
    2218             :  * The function returns 0 on success.  On error an error code is
    2219             :  * returned, all passed MPIs that might have been allocated up to this
    2220             :  * point are deallocated and set to NULL, and all passed buffers are
    2221             :  * either truncated if the caller supplied the buffer, or deallocated
    2222             :  * if the function allocated the buffer.
    2223             :  */
    2224             : gpg_err_code_t
    2225        8184 : _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
    2226             :                            const char *list, va_list arg_ptr)
    2227             : {
    2228             :   gpg_err_code_t rc;
    2229             :   const char *s, *s2;
    2230             :   gcry_mpi_t *array[20];
    2231             :   char arrayisdesc[20];
    2232             :   int idx;
    2233             :   gcry_sexp_t l1;
    2234        8184 :   int mode = '+'; /* Default to GCRYMPI_FMT_USG.  */
    2235        8184 :   gcry_sexp_t freethis = NULL;
    2236             : 
    2237        8184 :   memset (arrayisdesc, 0, sizeof arrayisdesc);
    2238             : 
    2239             :   /* First copy all the args into an array.  This is required so that
    2240             :      we are able to release already allocated MPIs if later an error
    2241             :      was found.  */
    2242       37453 :   for (s=list, idx=0; *s && idx < DIM (array); s++)
    2243             :     {
    2244       29272 :       if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
    2245             :         ;
    2246       19430 :       else if (whitespacep (s))
    2247             :         ;
    2248             :       else
    2249             :         {
    2250       19423 :           if (*s == '\'')
    2251             :             {
    2252           4 :               s++;
    2253           4 :               s2 = strchr (s, '\'');
    2254           4 :               if (!s2 || s2 == s)
    2255             :                 {
    2256             :                   /* Closing quote not found or empty string.  */
    2257           2 :                   return GPG_ERR_SYNTAX;
    2258             :                 }
    2259           2 :               s = s2;
    2260             :             }
    2261       19421 :           array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
    2262       19421 :           if (!array[idx])
    2263           1 :             return GPG_ERR_MISSING_VALUE; /* NULL pointer given.  */
    2264       19420 :           idx++;
    2265             :         }
    2266             :     }
    2267        8181 :   if (*s)
    2268           0 :     return GPG_ERR_LIMIT_REACHED;  /* Too many list elements.  */
    2269        8181 :   if (va_arg (arg_ptr, gcry_mpi_t *))
    2270           1 :     return GPG_ERR_INV_ARG;  /* Not enough list elemends.  */
    2271             : 
    2272             :   /* Drill down.  */
    2273       16377 :   while (path && *path)
    2274             :     {
    2275             :       size_t n;
    2276             : 
    2277          19 :       s = strchr (path, '!');
    2278          19 :       if (s == path)
    2279             :         {
    2280           1 :           rc = GPG_ERR_NOT_FOUND;
    2281           1 :           goto cleanup;
    2282             :         }
    2283          18 :       n = s? s - path : 0;
    2284          18 :       l1 = _gcry_sexp_find_token (sexp, path, n);
    2285          18 :       if (!l1)
    2286             :         {
    2287           1 :           rc = GPG_ERR_NOT_FOUND;
    2288           1 :           goto cleanup;
    2289             :         }
    2290          17 :       sexp = l1; l1 = NULL;
    2291          17 :       sexp_release (freethis);
    2292          17 :       freethis = sexp;
    2293          17 :       if (n)
    2294           8 :         path += n + 1;
    2295             :       else
    2296           9 :         path = NULL;
    2297             :     }
    2298             : 
    2299             : 
    2300             :   /* Now extract all parameters.  */
    2301       37406 :   for (s=list, idx=0; *s; s++)
    2302             :     {
    2303       29233 :       if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
    2304        4735 :         mode = *s;
    2305       24498 :       else if (whitespacep (s))
    2306             :         ;
    2307       24491 :       else if (*s == '?')
    2308             :         ; /* Only used via lookahead.  */
    2309             :       else
    2310             :         {
    2311       19384 :           if (*s == '\'')
    2312             :             {
    2313             :               /* Find closing quote, find token, set S to closing quote.  */
    2314           2 :               s++;
    2315           2 :               s2 = strchr (s, '\'');
    2316           2 :               if (!s2 || s2 == s)
    2317             :                 {
    2318             :                   /* Closing quote not found or empty string.  */
    2319           0 :                   rc = GPG_ERR_SYNTAX;
    2320           0 :                   goto cleanup;
    2321             :                 }
    2322           2 :               l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
    2323           2 :               s = s2;
    2324             :             }
    2325             :           else
    2326       19382 :             l1 = _gcry_sexp_find_token (sexp, s, 1);
    2327             : 
    2328       19384 :           if (!l1 && s[1] == '?')
    2329             :             {
    2330             :               /* Optional element not found.  */
    2331        6642 :               if (mode == '&')
    2332             :                 {
    2333           0 :                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2334           0 :                   if (!spec->data)
    2335             :                     {
    2336           0 :                       spec->size = 0;
    2337           0 :                       spec->off = 0;
    2338             :                     }
    2339           0 :                   spec->len = 0;
    2340             :                 }
    2341             :               else
    2342        3321 :                 *array[idx] = NULL;
    2343             :             }
    2344       16063 :           else if (!l1)
    2345             :             {
    2346           5 :               rc = GPG_ERR_NO_OBJ;  /* List element not found.  */
    2347           5 :               goto cleanup;
    2348             :             }
    2349             :            else
    2350             :             {
    2351       16058 :               if (mode == '&')
    2352             :                 {
    2353           4 :                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2354             : 
    2355           4 :                   if (spec->data)
    2356             :                     {
    2357             :                       const char *pbuf;
    2358             :                       size_t nbuf;
    2359             : 
    2360           2 :                       pbuf = _gcry_sexp_nth_data (l1, 1, &nbuf);
    2361           2 :                       if (!pbuf || !nbuf)
    2362             :                         {
    2363           0 :                           rc = GPG_ERR_INV_OBJ;
    2364           0 :                           goto cleanup;
    2365             :                         }
    2366           2 :                       if (spec->off + nbuf > spec->size)
    2367             :                         {
    2368           0 :                           rc = GPG_ERR_BUFFER_TOO_SHORT;
    2369           0 :                           goto cleanup;
    2370             :                         }
    2371           2 :                       memcpy ((char*)spec->data + spec->off, pbuf, nbuf);
    2372           2 :                       spec->len = nbuf;
    2373           2 :                       arrayisdesc[idx] = 1;
    2374             :                     }
    2375             :                   else
    2376             :                     {
    2377           2 :                       spec->data = _gcry_sexp_nth_buffer (l1, 1, &spec->size);
    2378           2 :                       if (!spec->data)
    2379             :                         {
    2380           0 :                           rc = GPG_ERR_INV_OBJ; /* Or out of core.  */
    2381           0 :                           goto cleanup;
    2382             :                         }
    2383           2 :                       spec->len = spec->size;
    2384           2 :                       spec->off = 0;
    2385           2 :                       arrayisdesc[idx] = 2;
    2386             :                     }
    2387             :                 }
    2388       16054 :               else if (mode == '/')
    2389        3501 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
    2390       12553 :               else if (mode == '-')
    2391          73 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
    2392             :               else
    2393       12480 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
    2394       16058 :               sexp_release (l1); l1 = NULL;
    2395       16058 :               if (!*array[idx])
    2396             :                 {
    2397           0 :                   rc = GPG_ERR_INV_OBJ;  /* Conversion failed.  */
    2398           0 :                   goto cleanup;
    2399             :                 }
    2400             :             }
    2401       19379 :           idx++;
    2402             :         }
    2403             :     }
    2404             : 
    2405        8173 :   sexp_release (freethis);
    2406        8173 :   return 0;
    2407             : 
    2408             :  cleanup:
    2409           7 :   sexp_release (freethis);
    2410           7 :   sexp_release (l1);
    2411          46 :   while (idx--)
    2412             :     {
    2413          32 :       if (!arrayisdesc[idx])
    2414             :         {
    2415          32 :           _gcry_mpi_release (*array[idx]);
    2416          32 :           *array[idx] = NULL;
    2417             :         }
    2418           0 :       else if (arrayisdesc[idx] == 1)
    2419             :         {
    2420             :           /* Caller provided buffer.  */
    2421           0 :           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2422           0 :           spec->len = 0;
    2423             :         }
    2424             :       else
    2425             :         {
    2426             :           /* We might have allocated a buffer.  */
    2427           0 :           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2428           0 :           xfree (spec->data);
    2429           0 :           spec->data = NULL;
    2430           0 :           spec->size = spec->off = spec->len = 0;
    2431             :         }
    2432             :      }
    2433           7 :   return rc;
    2434             : }
    2435             : 
    2436             : gpg_err_code_t
    2437        8164 : _gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path,
    2438             :                           const char *list, ...)
    2439             : {
    2440             :   gcry_err_code_t rc;
    2441             :   va_list arg_ptr;
    2442             : 
    2443        8164 :   va_start (arg_ptr, list);
    2444        8164 :   rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
    2445        8164 :   va_end (arg_ptr);
    2446        8164 :   return rc;
    2447             : }

Generated by: LCOV version 1.13