Subject: Re: bug#50985: Merging gnulib for Emacs 28.1?

From: Paul Eggert <[email-masked]>
Date: Tue, 5 Oct 2021 09:16:13 -0700

On 10/5/21 7:11 AM, Robert Pluim wrote:
> Probably. When it comes to gnulib I prefer to leave it to people who
> know what theyʼre doing :-)

We can't wait for *that* (:-), so I charged ahead and installed the 
attached patches into the emacs-28 branch. This fixed the md5_stream 
issue for me.

The key issue here is whether Emacs wants to use cryptography algorithms 
supported by the Linux kernel, if available. I expect that Emacs doesn't 
want to bother, because its use of md5_stream is not that performance- 
or security-relevant and because if we wanted Emacs to use the kernel 
stuff that'd drag in a lot more Gnulib modules which would be more 
trouble than it's worth. Comments welcome of course, since this is a 
judgment call.

I hadn't run into this earlier because I was doing a default 
configure+build, which on my platform didn't use native compilation.

From 18308b739a561bff677929da2a1412e91c0d05cd Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Tue, 5 Oct 2021 09:03:47 -0700
Subject: [PATCH 1/2] Tweak recent 'configure' fix

* configure.ac (gt_TYPE_WINT_T): Omit obsolete and
now-overridden definition.
---
 configure.ac | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 62bf25ebbf..e6ffea0637 100644
--- a/configure.ac
+++ b/configure.ac
@@ -874,9 +874,6 @@ AC_DEFUN
 done
 ac_func_list=$funcs
 # Emacs does not use the wchar or wctype-h modules.
-AC_DEFUN([gt_TYPE_WINT_T],
-  [GNULIB_OVERRIDES_WINT_T=0
-   AC_SUBST([GNULIB_OVERRIDES_WINT_T])])
 AC_DEFUN([gt_TYPE_WINT_T],
   [GNULIBHEADERS_OVERRIDE_WINT_T=0
    AC_SUBST([GNULIBHEADERS_OVERRIDE_WINT_T])])
-- 
2.30.2

From 4d76765b6c8a3117c436ccc93572cddfd8d17d7c Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Tue, 5 Oct 2021 09:08:02 -0700
Subject: [PATCH 2/2] Fix md5 issue in recent Gnulib merge
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When configured --with-native-compilation, Emacs needs md5_stream.
Problem reported by Andy Moreton (Bug#50985#23).
* admin/merge-gnulib (GNULIB_MODULES): Add crypto/md5,
needed for --with-native-compilation.
(AVOIDED_MODULES): Avoid crypto/af_alg, since Emacs doesn’t
need to bother with kernel-supported cryptography algorithms.
* lib/gnulib.mk.in, m4/gnulib-comp.m4:
Regenerate by running admin/merge-gnulib.
* lib/md5-stream.c: New file, copied from Gnulib.
---
 admin/merge-gnulib |   5 +-
 lib/gnulib.mk.in   |  12 +++-
 lib/md5-stream.c   | 141 +++++++++++++++++++++++++++++++++++++++++++++
 m4/gnulib-comp.m4  |   2 +
 4 files changed, 157 insertions(+), 3 deletions(-)
 create mode 100644 lib/md5-stream.c

diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 10cc73aa73..886f37e28c 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -30,7 +30,8 @@ GNULIB_MODULES=
   canonicalize-lgpl
   careadlinkat close-stream copy-file-range
   count-leading-zeros count-one-bits count-trailing-zeros
-  crypto/md5-buffer crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer
+  crypto/md5 crypto/md5-buffer
+  crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer
   d-type diffseq double-slash-root dtoastr dtotimespec dup2
   environ execinfo explicit_bzero faccessat
   fchmodat fcntl fcntl-h fdopendir file-has-acl
@@ -49,7 +50,7 @@ GNULIB_MODULES=
 '
 
 AVOIDED_MODULES='
-  btowc close dup fchdir fstat langinfo lock
+  btowc close crypto/af_alg dup fchdir fstat langinfo lock
   mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo
   openat-die opendir pthread-h raise
   save-cwd select setenv sigprocmask stat stdarg stdbool
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index bac27f3a68..e9a1a5dc02 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -36,6 +36,7 @@
 #  --no-vc-files \
 #  --avoid=btowc \
 #  --avoid=close \
+#  --avoid=crypto/af_alg \
 #  --avoid=dup \
 #  --avoid=fchdir \
 #  --avoid=fstat \
@@ -79,6 +80,7 @@
 #  count-leading-zeros \
 #  count-one-bits \
 #  count-trailing-zeros \
+#  crypto/md5 \
 #  crypto/md5-buffer \
 #  crypto/sha1-buffer \
 #  crypto/sha256-buffer \
@@ -544,8 +546,8 @@ GL_GNULIB_WRITE = @GL_GNULIB_WRITE@
 GL_GNULIB__EXIT = @GL_GNULIB__EXIT@
 GMALLOC_OBJ = @GMALLOC_OBJ@
 GMP_H = @GMP_H@
-GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@
 GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@
+GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@
 GNULIB_WARN_CFLAGS = @GNULIB_WARN_CFLAGS@
 GNUSTEP_CFLAGS = @GNUSTEP_CFLAGS@
 GNU_OBJC_CFLAGS = @GNU_OBJC_CFLAGS@
@@ -1473,6 +1475,14 @@ EXTRA_DIST += count-trailing-zeros.h
 endif
 ## end   gnulib module count-trailing-zeros
 
+## begin gnulib module crypto/md5
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5))
+
+libgnu_a_SOURCES += md5-stream.c
+
+endif
+## end   gnulib module crypto/md5
+
 ## begin gnulib module crypto/md5-buffer
 ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5-buffer))
 
diff --git a/lib/md5-stream.c b/lib/md5-stream.c
new file mode 100644
index 0000000000..fb483b7334
--- /dev/null
+++ b/lib/md5-stream.c
@@ -0,0 +1,141 @@
+/* Functions to compute MD5 message digest of files or memory blocks.
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2021 Free Software
+   Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Ulrich Drepper <[email-masked]>, 1995.  */
+
+#include <config.h>
+
+/* Specification.  */
+#if HAVE_OPENSSL_MD5
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
+#include "md5.h"
+
+#include <stdlib.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#include "af_alg.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+/* We need to keep the namespace clean so define the MD5 function
+   protected using leading __ .  */
+# define md5_init_ctx __md5_init_ctx
+# define md5_process_block __md5_process_block
+# define md5_process_bytes __md5_process_bytes
+# define md5_finish_ctx __md5_finish_ctx
+# define md5_stream __md5_stream
+#endif
+
+#define BLOCKSIZE 32768
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#endif
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (FILE *stream, void *resblock)
+{
+  switch (afalg_stream (stream, "md5", resblock, MD5_DIGEST_SIZE))
+    {
+    case 0: return 0;
+    case -EIO: return 1;
+    }
+
+  char *buffer = malloc (BLOCKSIZE + 72);
+  if (!buffer)
+    return 1;
+
+  struct md5_ctx ctx;
+  md5_init_ctx (&ctx);
+  size_t sum;
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+         computation function processes the whole buffer so that with the
+         next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      while (1)
+        {
+          /* Either process a partial fread() from this loop,
+             or the fread() in afalg_stream may have gotten EOF.
+             We need to avoid a subsequent fread() as EOF may
+             not be sticky.  For details of such systems, see:
+             https://sourceware.org/bugzilla/show_bug.cgi?id=1190  */
+          if (feof (stream))
+            goto process_partial_block;
+
+          n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+          sum += n;
+
+          if (sum == BLOCKSIZE)
+            break;
+
+          if (n == 0)
+            {
+              /* Check for the error flag IFF N == 0, so that we don't
+                 exit the loop after a partial read due to e.g., EAGAIN
+                 or EWOULDBLOCK.  */
+              if (ferror (stream))
+                {
+                  free (buffer);
+                  return 1;
+                }
+              goto process_partial_block;
+            }
+        }
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+         BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+process_partial_block:
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  free (buffer);
+  return 0;
+}
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index dd5bde8d79..a795fe7651 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -63,6 +63,7 @@ AC_DEFUN
   # Code from module count-leading-zeros:
   # Code from module count-one-bits:
   # Code from module count-trailing-zeros:
+  # Code from module crypto/md5:
   # Code from module crypto/md5-buffer:
   # Code from module crypto/sha1-buffer:
   # Code from module crypto/sha256-buffer:
@@ -1207,6 +1208,7 @@ AC_DEFUN
   lib/malloc/scratch_buffer_grow.c
   lib/malloc/scratch_buffer_grow_preserve.c
   lib/malloc/scratch_buffer_set_array_size.c
+  lib/md5-stream.c
   lib/md5.c
   lib/md5.h
   lib/memmem.c
-- 
2.30.2