Tim Rühsen wrote:
> I could invite you (or anybody else) to view the detected defects. Just
> give me an OK and/or your email address before I do so.
> 
> From what I can quickly see, some defects might be quite serious.

What I can see (in the limited set of gnulib modules that wget uses):

1) Coverity suggests to use 'memmove' instead of 'memcpy' in a couple
of places where it cannot prove that the source and destination memory
regions don't overlap.

I don't know what could make the coverity warnings disappear, but at least
we can add comments that help us verify that there is no issue. Invariants,
as usual.

2) A false warning at
     len >> 31 >> 31 >> 2
because the code is prepared for 128-bit integers but coverity "knows" that
'len' is at most 64 bits wide.

3) malloc/free related warnings in glob.c.

Please review the three attached patches.
From 3e7178b337e3a83df9e4f36a4aef516f089e3796 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 31 Mar 2017 22:03:49 +0200
Subject: [PATCH 1/3] md5, sha1, sha256, sha512: Add comments regarding
 correctness.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lib/md5.h (buflen): Add comments regarding range.
* lib/sha1.h (buflen): Likewise.
* lib/sha256.h (buflen): Likewise.
* lib/sha512.h (buflen): Likewise.
* lib/md5.c (md5_process_bytes): Add comment why memmove is not needed.
* lib/sha1.c (sha1_process_bytes): Likewise.
* lib/sha256.c (sha256_process_bytes): Likewise.
* lib/sha512.c (sha512_process_bytes): Likewise.
Reported by Coverity via Tim Rühsen.
---
 ChangeLog    | 13 +++++++++++++
 lib/md5.c    |  5 ++++-
 lib/md5.h    |  4 ++--
 lib/sha1.c   |  5 ++++-
 lib/sha1.h   |  4 ++--
 lib/sha256.c |  5 ++++-
 lib/sha256.h |  4 ++--
 lib/sha512.c |  5 ++++-
 lib/sha512.h |  4 ++--
 9 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ad7ae9e..7c15292 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2017-03-31  Bruno Haible  <br...@clisp.org>
+
+	md5, sha1, sha256, sha512: Add comments regarding correctness.
+	* lib/md5.h (buflen): Add comments regarding range.
+	* lib/sha1.h (buflen): Likewise.
+	* lib/sha256.h (buflen): Likewise.
+	* lib/sha512.h (buflen): Likewise.
+	* lib/md5.c (md5_process_bytes): Add comment why memmove is not needed.
+	* lib/sha1.c (sha1_process_bytes): Likewise.
+	* lib/sha256.c (sha256_process_bytes): Likewise.
+	* lib/sha512.c (sha512_process_bytes): Likewise.
+	Reported by Coverity via Tim Rühsen.
+
 2017-03-22  Paul Eggert  <egg...@cs.ucla.edu>
 
 	getopt: merge from glibc
diff --git a/lib/md5.c b/lib/md5.c
index 9f5237e..8650957 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -246,7 +246,8 @@ md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
           md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
 
           ctx->buflen &= 63;
-          /* The regions in the following copy operation cannot overlap.  */
+          /* The regions in the following copy operation cannot overlap,
+             because ctx->buflen < 64 ≤ (left_over + add) & ~63.  */
           memcpy (ctx->buffer,
                   &((char *) ctx->buffer)[(left_over + add) & ~63],
                   ctx->buflen);
@@ -288,6 +289,8 @@ md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
         {
           md5_process_block (ctx->buffer, 64, ctx);
           left_over -= 64;
+          /* The regions in the following copy operation cannot overlap,
+             because left_over ≤ 64.  */
           memcpy (ctx->buffer, &ctx->buffer[16], left_over);
         }
       ctx->buflen = left_over;
diff --git a/lib/md5.h b/lib/md5.h
index 9c2c098..543a366 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -74,8 +74,8 @@ struct md5_ctx
   uint32_t D;
 
   uint32_t total[2];
-  uint32_t buflen;
-  uint32_t buffer[32];
+  uint32_t buflen;     /* ≥ 0, ≤ 128 */
+  uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
 };
 
 /*
diff --git a/lib/sha1.c b/lib/sha1.c
index 87c5771..6908650 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -233,7 +233,8 @@ sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
           sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
 
           ctx->buflen &= 63;
-          /* The regions in the following copy operation cannot overlap.  */
+          /* The regions in the following copy operation cannot overlap,
+             because ctx->buflen < 64 ≤ (left_over + add) & ~63.  */
           memcpy (ctx->buffer,
                   &((char *) ctx->buffer)[(left_over + add) & ~63],
                   ctx->buflen);
@@ -275,6 +276,8 @@ sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
         {
           sha1_process_block (ctx->buffer, 64, ctx);
           left_over -= 64;
+          /* The regions in the following copy operation cannot overlap,
+             because left_over ≤ 64.  */
           memcpy (ctx->buffer, &ctx->buffer[16], left_over);
         }
       ctx->buflen = left_over;
diff --git a/lib/sha1.h b/lib/sha1.h
index 38e82f3..0deb7ba 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -46,8 +46,8 @@ struct sha1_ctx
   uint32_t E;
 
   uint32_t total[2];
-  uint32_t buflen;
-  uint32_t buffer[32];
+  uint32_t buflen;     /* ≥ 0, ≤ 128 */
+  uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
 };
 
 /* Initialize structure containing state of computation. */
diff --git a/lib/sha256.c b/lib/sha256.c
index 03d3899..c0fb8be 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -366,7 +366,8 @@ sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx)
           sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
 
           ctx->buflen &= 63;
-          /* The regions in the following copy operation cannot overlap.  */
+          /* The regions in the following copy operation cannot overlap,
+             because ctx->buflen < 64 ≤ (left_over + add) & ~63.  */
           memcpy (ctx->buffer,
                   &((char *) ctx->buffer)[(left_over + add) & ~63],
                   ctx->buflen);
@@ -408,6 +409,8 @@ sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx)
         {
           sha256_process_block (ctx->buffer, 64, ctx);
           left_over -= 64;
+          /* The regions in the following copy operation cannot overlap,
+             because left_over ≤ 64.  */
           memcpy (ctx->buffer, &ctx->buffer[16], left_over);
         }
       ctx->buflen = left_over;
diff --git a/lib/sha256.h b/lib/sha256.h
index ffb91fa..348b76e 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -44,8 +44,8 @@ struct sha256_ctx
   uint32_t state[8];
 
   uint32_t total[2];
-  size_t buflen;
-  uint32_t buffer[32];
+  size_t buflen;       /* ≥ 0, ≤ 128 */
+  uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
 };
 
 /* Initialize structure containing state of computation. */
diff --git a/lib/sha512.c b/lib/sha512.c
index 6876bfd..dbde671 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -374,7 +374,8 @@ sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
           sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
 
           ctx->buflen &= 127;
-          /* The regions in the following copy operation cannot overlap.  */
+          /* The regions in the following copy operation cannot overlap,
+             because ctx->buflen < 128 ≤ (left_over + add) & ~127.  */
           memcpy (ctx->buffer,
                   &((char *) ctx->buffer)[(left_over + add) & ~127],
                   ctx->buflen);
@@ -416,6 +417,8 @@ sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
         {
           sha512_process_block (ctx->buffer, 128, ctx);
           left_over -= 128;
+          /* The regions in the following copy operation cannot overlap,
+             because left_over ≤ 128.  */
           memcpy (ctx->buffer, &ctx->buffer[16], left_over);
         }
       ctx->buflen = left_over;
diff --git a/lib/sha512.h b/lib/sha512.h
index 121e6c3..4460e6c 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -44,8 +44,8 @@ struct sha512_ctx
   u64 state[8];
 
   u64 total[2];
-  size_t buflen;
-  u64 buffer[32];
+  size_t buflen;  /* ≥ 0, ≤ 256 */
+  u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */
 };
 
 /* Initialize structure containing state of computation. */
-- 
2.7.4

From 0eee3ccaae5bb3d0016a0da8b8e5108767c02748 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 31 Mar 2017 22:41:38 +0200
Subject: [PATCH 2/3] glob: Fix memory leaks.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lib/glob.c (glob): Free allocated memory before returning.
Reported by Coverity via Tim Rühsen.
---
 ChangeLog  |  6 ++++++
 lib/glob.c | 13 +++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7c15292..cca7542 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2017-03-31  Bruno Haible  <br...@clisp.org>
 
+	glob: Fix memory leaks.
+	* lib/glob.c (glob): Free allocated memory before returning.
+	Reported by Coverity via Tim Rühsen.
+
+2017-03-31  Bruno Haible  <br...@clisp.org>
+
 	md5, sha1, sha256, sha512: Add comments regarding correctness.
 	* lib/md5.h (buflen): Add comments regarding range.
 	* lib/sha1.h (buflen): Likewise.
diff --git a/lib/glob.c b/lib/glob.c
index e69a96e..1337817 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -789,10 +789,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                               malloc_home_dir = 1;
                             }
                           memcpy (home_dir, p->pw_dir, home_dir_len);
-
-                          free (pwtmpbuf);
                         }
                     }
+                  free (malloc_pwtmpbuf);
+                }
+              else
+                {
+                  if (__glibc_unlikely (malloc_name))
+                    free (name);
                 }
             }
           if (home_dir == NULL || home_dir[0] == '\0')
@@ -847,6 +851,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               dirname = newp;
               dirlen += home_len - 1;
               malloc_dirname = !use_alloca;
+
+              if (__glibc_unlikely (malloc_home_dir))
+                free (home_dir);
             }
           dirname_modified = 1;
         }
@@ -1048,6 +1055,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
           if (newcount > SIZE_MAX / sizeof (char *) - 2)
             {
             nospace:
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
               free (pglob->gl_pathv);
               pglob->gl_pathv = NULL;
               pglob->gl_pathc = 0;
-- 
2.7.4

From b1d7f3165ba1c7a44a29017eb80491094aa240ba Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 31 Mar 2017 22:43:35 +0200
Subject: [PATCH 3/3] glob: Fix invalid free() call.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lib/glob.c (glob): Reset malloc_home_dir when assigning a pointer to
static storage to home_dir.
Reported by Coverity via Tim Rühsen.
---
 ChangeLog  | 7 +++++++
 lib/glob.c | 5 ++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index cca7542..2e01161 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2017-03-31  Bruno Haible  <br...@clisp.org>
 
+	glob: Fix invalid free() call.
+	* lib/glob.c (glob): Reset malloc_home_dir when assigning a pointer to
+	static storage to home_dir.
+	Reported by Coverity via Tim Rühsen.
+
+2017-03-31  Bruno Haible  <br...@clisp.org>
+
 	glob: Fix memory leaks.
 	* lib/glob.c (glob): Free allocated memory before returning.
 	Reported by Coverity via Tim Rühsen.
diff --git a/lib/glob.c b/lib/glob.c
index 1337817..9305038 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -809,7 +809,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                   goto out;
                 }
               else
-                home_dir = (char *) "~"; /* No luck.  */
+                {
+                  home_dir = (char *) "~"; /* No luck.  */
+                  malloc_home_dir = 0;
+                }
             }
 #  endif /* WINDOWS32 */
 # endif
-- 
2.7.4

Reply via email to