]> Savannah Git Hosting - gnulib.git/commitdiff
af_alg: Fix bug with streams that are not at position 0.
authorBruno Haible <bruno@clisp.org>
Sun, 6 May 2018 11:30:24 +0000 (13:30 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 6 May 2018 11:30:24 +0000 (13:30 +0200)
* lib/af_alg.c (afalg_stream): Before sendfile, invoke fflush. Don't
assume that the stream is positioned at position 0.
* lib/af_alg.h (afalg_stream): Mention restriction regarding the state
of the stream.
* lib/md5.h (md5_stream): Likewise.
* lib/sha1.h (sha1_stream): Likewise.
* lib/sha256.h (sha256_stream, sha224_stream): Likewise.
* lib/sha512.h (sha512_stream, sha384_stream): Likewise.
* modules/crypto/af_alg (Depends-on): Add fflush, lseek.

ChangeLog
lib/af_alg.c
lib/af_alg.h
lib/md5.h
lib/sha1.h
lib/sha256.h
lib/sha512.h
modules/crypto/af_alg

index 49624ecfb2ca1bdeaad70e33cf024460825a7180..20e13168e2df9a90044d5b36d5eb98b662b28132 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2018-05-06  Bruno Haible  <bruno@clisp.org>
 
+       af_alg: Fix bug with streams that are not at position 0.
+       * lib/af_alg.c (afalg_stream): Before sendfile, invoke fflush. Don't
+       assume that the stream is positioned at position 0.
+       * lib/af_alg.h (afalg_stream): Mention restriction regarding the state
+       of the stream.
+       * lib/md5.h (md5_stream): Likewise.
+       * lib/sha1.h (sha1_stream): Likewise.
+       * lib/sha256.h (sha256_stream, sha224_stream): Likewise.
+       * lib/sha512.h (sha512_stream, sha384_stream): Likewise.
+       * modules/crypto/af_alg (Depends-on): Add fflush, lseek.
+
        crypto/{md5,sha1,sha256,sha512} tests: Enhance test.
        * tests/test-digest.h (test_digest_on_files): Add a test with a FILE
        stream that is not positioned at the beginning.
index 97bdff516bd5c83c3bc7a59f164d8817552be427..79e219586e2e2e8c1555581df79ff58f7381613f 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <unistd.h>
 #include <string.h>
+#include <stdio.h>
+#include <errno.h>
 #include <linux/if_alg.h>
 #include <sys/stat.h>
 #include <sys/sendfile.h>
@@ -65,12 +67,35 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
     }
 
   /* if file is a regular file, attempt sendfile to pipe the data.  */
+  int fd = fileno (stream);
   struct stat st;
-  if (fstat (fileno (stream), &st) == 0
+  if (fstat (fd, &st) == 0
       && (S_ISREG (st.st_mode) || S_TYPEISSHM (&st) || S_TYPEISTMO (&st))
       && 0 < st.st_size && st.st_size <= SYS_BUFSIZE_MAX)
     {
-      if (sendfile (ofd, fileno (stream), NULL, st.st_size) != st.st_size)
+      /* Make sure the offset of fileno (stream) reflects how many bytes
+         have been read from stream before this function got invoked.
+         Note: fflush on an input stream after ungetc does not work as expected
+         on some platforms.  Therefore this situation is not supported here.  */
+      if (fflush (stream))
+        {
+#if defined _WIN32 && ! defined __CYGWIN__
+          ret = -EIO;
+#else
+          ret = -errno;
+#endif
+          goto out_cfd;
+        }
+
+      off_t nbytes = st.st_size - lseek (fd, 0, SEEK_CUR);
+      /* On Linux < 4.9, the value for an empty stream is wrong (all zeroes).
+         See <https://patchwork.kernel.org/patch/9434741/>.  */
+      if (nbytes <= 0)
+        {
+          ret = -EAFNOSUPPORT;
+          goto out_ofd;
+        }
+      if (sendfile (ofd, fd, NULL, nbytes) != nbytes)
         {
           ret = -EIO;
           goto out_ofd;
index a15a9565132de4dfd436ce2e28b7c99fbc11d02d..dfcc995964295b53efb5f9449baf3515b782ce64 100644 (file)
@@ -38,8 +38,13 @@ extern "C" {
 # if USE_LINUX_CRYPTO_API
 
 /* Compute a message digest of the contents of a file.
+
    STREAM is an open file stream.  Regular files are handled more efficiently.
+   The contents of STREAM from its current position to its end will be read.
+   The case that the last operation on STREAM was an 'ungetc' is not supported.
+
    ALG is the message digest algorithm; see the file /proc/crypto.
+
    RESBLOCK points to a block of HASHLEN bytes, for the result.
    HASHLEN must be the length of the message digest, in bytes, in particular:
 
index d5d3c0167f7538f1eb03cc9852f9f9058b5f7446..47dc7d41b00f60a3734e95c9299a412d530ffe0c 100644 (file)
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -122,8 +122,11 @@ extern void *__md5_buffer (const char *buffer, size_t len,
                            void *resblock) __THROW;
 
 # endif
-/* Compute MD5 message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 16 bytes
+/* Compute MD5 message digest for bytes read from STREAM.
+   STREAM is an open file stream.  Regular files are handled more efficiently.
+   The contents of STREAM from its current position to its end will be read.
+   The case that the last operation on STREAM was an 'ungetc' is not supported.
+   The resulting message digest number will be written into the 16 bytes
    beginning at RESBLOCK.  */
 extern int __md5_stream (FILE *stream, void *resblock) __THROW;
 
index e41ce4bfeefec70373508e71013b0e9c810cbb92..cca83fc91a41dc5767790ecb9e414937d6b17672 100644 (file)
@@ -87,8 +87,11 @@ extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
 extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
 
 # endif
-/* Compute SHA1 message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 20 bytes
+/* Compute SHA1 message digest for bytes read from STREAM.
+   STREAM is an open file stream.  Regular files are handled more efficiently.
+   The contents of STREAM from its current position to its end will be read.
+   The case that the last operation on STREAM was an 'ungetc' is not supported.
+   The resulting message digest number will be written into the 20 bytes
    beginning at RESBLOCK.  */
 extern int sha1_stream (FILE *stream, void *resblock);
 
index e3449864bb674de96b25470c7274943de10ab989..19ed3ccd4d0ef6e5b3250bef3b7e57ebf6369c32 100644 (file)
@@ -89,8 +89,11 @@ extern void *sha256_buffer (const char *buffer, size_t len, void *resblock);
 extern void *sha224_buffer (const char *buffer, size_t len, void *resblock);
 
 # endif
-/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 32 (28) bytes
+/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.
+   STREAM is an open file stream.  Regular files are handled more efficiently.
+   The contents of STREAM from its current position to its end will be read.
+   The case that the last operation on STREAM was an 'ungetc' is not supported.
+   The resulting message digest number will be written into the 32 (28) bytes
    beginning at RESBLOCK.  */
 extern int sha256_stream (FILE *stream, void *resblock);
 extern int sha224_stream (FILE *stream, void *resblock);
index 6a0aadba02fdbd13c716394df770443be5e38a56..2c39ab195cfb7e1010e69dff76c4200650ae4c55 100644 (file)
@@ -92,8 +92,11 @@ extern void *sha512_buffer (const char *buffer, size_t len, void *resblock);
 extern void *sha384_buffer (const char *buffer, size_t len, void *resblock);
 
 # endif
-/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 64 (48) bytes
+/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.
+   STREAM is an open file stream.  Regular files are handled more efficiently.
+   The contents of STREAM from its current position to its end will be read.
+   The case that the last operation on STREAM was an 'ungetc' is not supported.
+   The resulting message digest number will be written into the 64 (48) bytes
    beginning at RESBLOCK.  */
 extern int sha512_stream (FILE *stream, void *resblock);
 extern int sha384_stream (FILE *stream, void *resblock);
index c9602dc3b7d4bd9251dd12b0f4cf3a52caea1a65..0c498e05c8eb096278b87b7ca68cfda0c6a31420 100644 (file)
@@ -8,6 +8,8 @@ lib/sys-limits.h
 m4/af_alg.m4
 
 Depends-on:
+fflush          [test $USE_AF_ALG = 1]
+lseek           [test $USE_AF_ALG = 1]
 sys_socket
 sys_stat