daemon: Fix 'HashSink::currentHash()'.
authorLudovic Courtès <ludo@gnu.org>
Wed, 18 Dec 2013 20:48:57 +0000 (21:48 +0100)
committerLudovic Courtès <ludo@gnu.org>
Wed, 18 Dec 2013 23:02:49 +0000 (00:02 +0100)
Before that, calls to 'HashSink::currentHash()' would eventually lead to
a segfault because the underlying gcrypt handle has been closed.  (Note
that this method is only used via 'importPaths' and 'exportPath', though.)

* nix/libutil/gcrypt-hash.hh (struct guix_hash_context): Add a
  constructor and a copy constructor; move out of 'extern "C"'.
* nix/libutil/gcrypt-hash.cc (guix_hash_final): Clear 'md_handle' upon
  exit.
* nix/sync-with-upstream (top_srcdir): Change hash.{cc,hh} to read
  'struct Ctx' instead of 'union Ctx'.

nix/libutil/gcrypt-hash.cc
nix/libutil/gcrypt-hash.hh
nix/sync-with-upstream

index 553f633..c4ae7bf 100644 (file)
@@ -45,6 +45,7 @@ guix_hash_final (void *resbuf, struct guix_hash_context *ctx,
   memcpy (resbuf, gcry_md_read (ctx->md_handle, algo),
          gcry_md_get_algo_dlen (algo));
   gcry_md_close (ctx->md_handle);
+  ctx->md_handle = NULL;
 }
 
 }
index d93a6eb..11f0611 100644 (file)
 #include <gcrypt.h>
 #include <unistd.h>
 
-extern "C" {
-
 struct guix_hash_context
 {
+  /* This copy constructor is needed in 'HashSink::currentHash()' where we
+     expect the copy of a 'Ctx' object to yield a truly different context.  */
+  guix_hash_context (guix_hash_context &ref)
+  {
+    if (ref.md_handle == NULL)
+      md_handle = NULL;
+    else
+      gcry_md_copy (&md_handle, ref.md_handle);
+  }
+
+  /* Make sure 'md_handle' is always initialized.  */
+  guix_hash_context (): md_handle (NULL) { };
+
   gcry_md_hd_t md_handle;
 };
 
+extern "C" {
 extern void guix_hash_init (struct guix_hash_context *ctx, int algo);
 extern void guix_hash_update (struct guix_hash_context *ctx, const void *buffer,
                              size_t len);
 extern void guix_hash_final (void *resbuf, struct guix_hash_context *ctx,
                             int algo);
-
 }
index 535763d..bb3a68b 100755 (executable)
@@ -70,3 +70,11 @@ cp -v "$top_srcdir/nix-upstream/AUTHORS" "$top_srcdir/nix"
 # Substitutions.
 sed -i "$top_srcdir/nix/libstore/gc.cc"                                        \
     -e 's|/nix/find-runtime-roots\.pl|/guix/list-runtime-roots|g'
+
+# Our 'guix_hash_context' structure has a copy constructor, specifically to
+# handle the use case in 'HashSink::currentHash()' where the copy of the
+# context is expected to truly copy the underlying hash context.  The copy
+# constructor cannot be used in 'Ctx' if that's a union, so turn it into a
+# structure (we can afford to two wasted words.)
+sed -i "$top_srcdir/nix/libutil/hash".{cc,hh}  \
+    -e 's|union Ctx|struct Ctx|g'