tests: Check the result of all gcry_control operations.
[libgcrypt.git] / tests / t-sexp.c
index 3510382..2b33520 100644 (file)
@@ -28,7 +28,7 @@
 #include <assert.h>
 #include "../src/gcrypt-int.h"
 
-#define PGMNAME "t-sexp"
+#define PGM "t-sexp"
 #include "t-common.h"
 
 
@@ -81,7 +81,7 @@ hex2mpiopa (const char *string)
     die ("hex2mpiopa '%s' failed: parser error\n", string);
   val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
   if (!buffer)
-    die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
+    die ("hex2mpiopa '%s' failed: set_opaque error\n", string);
   return val;
 }
 
@@ -387,11 +387,46 @@ canon_len (void)
 }
 
 
+/* Compare SE to the canonical formatted expression in
+ * (CANON,CANONLEN).  This is done by a converting SE to canonical
+ * format and doing a byte compare.  Returns 0 if they match.  */
+static int
+compare_to_canon (gcry_sexp_t se, const unsigned char *canon, size_t canonlen)
+{
+  size_t n, n1;
+  char *p1;
+
+  n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
+  if (!n1)
+    {
+      fail ("get required length in compare_to_canon failed\n");
+      return -1;
+    }
+  p1 = gcry_xmalloc (n1);
+  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
+  if (n1 != n+1)
+    {
+      fail ("length mismatch in compare_to_canon detected\n");
+      xfree (p1);
+      return -1;
+    }
+  if (n1 != canonlen || memcmp (p1, canon, canonlen))
+    {
+      xfree (p1);
+      return -1;
+    }
+  xfree (p1);
+  return 0;
+}
+
+
 static void
 back_and_forth_one (int testno, const char *buffer, size_t length)
 {
   gcry_error_t rc;
   gcry_sexp_t se, se1;
+  unsigned char *canon;
+  size_t canonlen;  /* Including the hidden nul suffix.  */
   size_t n, n1;
   char *p1;
 
@@ -409,11 +444,14 @@ back_and_forth_one (int testno, const char *buffer, size_t length)
     }
   p1 = gcry_xmalloc (n1);
   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
-  if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
+  if (n1 != n+1) /* sprints adds an extra 0 but does not return it. */
     {
       fail ("baf %d: length mismatch for canon\n", testno);
       return;
     }
+  canonlen = n1;
+  canon = gcry_malloc (canonlen);
+  memcpy (canon, p1, canonlen);
   rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
   if (rc)
     {
@@ -449,9 +487,40 @@ back_and_forth_one (int testno, const char *buffer, size_t length)
     fail ("baf %d: memory corrupted (3)\n", testno);
   gcry_free (p1);
 
+  /* Check converting to advanced format.  */
+  n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+  if (!n1)
+    {
+      fail ("baf %d: get required length for advanced failed\n", testno);
+      return;
+    }
+  p1 = gcry_xmalloc (n1);
+  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, p1, n1);
+  if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
+    {
+      fail ("baf %d: length mismatch for advanced\n", testno);
+      return;
+    }
+  rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
+  if (rc)
+    {
+      fail ("baf %d: gcry_sexp_create failed: %s\n",
+            testno, gpg_strerror (rc));
+      return;
+    }
+  if (compare_to_canon (se1, canon, canonlen))
+    {
+      fail ("baf %d: converting to advanced failed: %s\n",
+            testno, gpg_strerror (rc));
+      return;
+    }
+  gcry_sexp_release (se1);
+
+
   /* FIXME: we need a lot more tests */
 
   gcry_sexp_release (se);
+  xfree (canon);
 }
 
 
@@ -474,6 +543,13 @@ back_and_forth (void)
 "   #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
 "  )\n"
 " )\n", 0 },
+    { "((sha1 #8B98CBF4A9823CA7# \"2097\") #3B6FC9#)", 0 },
+    { "((4:sha18:\x8B\x98\xCB\xF4\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
+    { "((4:sha18:\x8B\x98\xCB\x22\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
+    { "((sha1 #64652267686970C9# \"2097\") #3B6FC9#)", 0 },
+    { "((4:sha18:\x64\x65\x22\x67\x68\xc3\xa4\x71""4:2097)3:\x3B\x6F\xC9)", 0},
+    { "((sha1 \"defghäq\" \"2097\") #3B6FC9#)", 0 },
+    { "((sha1 \"de\\\"ghäq\" \"2097\") #3B6FC9#)", 0 },
     { NULL, 0 }
   };
   int idx;
@@ -978,6 +1054,76 @@ check_extract_param (void)
 }
 
 
+/* A test based on bug 1594.  */
+static void
+bug_1594 (void)
+{
+static char thing[] =
+  "(signature"
+  " (public-key"
+  "  (rsa"
+  "   (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
+  "       6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
+  "       6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
+  "       C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
+  "       CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
+  "       54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
+  "       13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
+  "       A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
+  "       F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
+  "       A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
+  "       E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
+  "       E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
+  "       923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
+  "       EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
+  "       2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
+  "       95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
+  "       67#)"
+  "   (e #010001#))))";
+  gcry_sexp_t sig, pubkey, n, n_val;
+
+  info ("checking fix for bug 1594\n");
+
+  if (gcry_sexp_new (&sig, thing, 0, 1))
+    die ("scanning fixed string failed\n");
+  pubkey = gcry_sexp_find_token (sig, "public-key", 0);
+  gcry_sexp_release (sig);
+  if (!pubkey)
+    {
+      fail ("'public-key' token not found");
+      return;
+    }
+  n = gcry_sexp_find_token (pubkey, "n", 0);
+  if (!n)
+    {
+      fail ("'n' token not found");
+      gcry_sexp_release (pubkey);
+      return;
+    }
+  n_val = gcry_sexp_nth (n, 1);
+  /* Bug 1594 would require the following test:
+   *   if (n_val)
+   *     fail ("extracting 1-th of 'n' list did not fail");
+   * However, we meanwhile modified the S-expression functions to
+   * behave like Scheme to allow the access of any element of a list.
+   */
+  if (!n_val)
+    fail ("extracting 1-th of 'n' list failed");
+  /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)"  */
+  gcry_sexp_release (n_val);
+  n_val = gcry_sexp_nth (n, 2);
+  if (n_val)
+    fail ("extracting 2-th of 'n' list did not fail");
+  n_val = gcry_sexp_nth (n, 0);
+  if (!n_val)
+    fail ("extracting 0-th of 'n' list failed");
+  /*gcry_log_debugsxp ("0-th", n_val); => "(n)"  */
+  if (gcry_sexp_nth (n_val, 1))
+    fail ("extracting 1-th of car of 'n' list did not fail");
+  gcry_sexp_release (n_val);
+  gcry_sexp_release (n);
+  gcry_sexp_release (pubkey);
+}
 
 
 int
@@ -1000,7 +1146,7 @@ main (int argc, char **argv)
       else if (!strcmp (*argv, "--help"))
         {
           puts (
-"usage: " PGMNAME " [options]\n"
+"usage: " PGM " [options]\n"
 "\n"
 "Options:\n"
 "  --verbose      Show what is going on\n"
@@ -1023,23 +1169,24 @@ main (int argc, char **argv)
     }
 
   if (debug)
-    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
-  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+  xgcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
+  xgcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch");
   /* #include "../src/gcrypt-int.h" indicates that internal interfaces
      may be used; thus better do an exact version check. */
   if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
     die ("exact version match failed");
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
   basic ();
   canon_len ();
   back_and_forth ();
   check_sscan ();
   check_extract_param ();
+  bug_1594 ();
 
-  return errorcount? 1:0;
+  return error_count? 1:0;
 }