> Therefore I think it would be good to add a "Shrink BUF before returning it."
> logic also to
>   areadlink-with-size.c
>   areadlinkat-with-size.c
>   etc.

Done as follows:
- For areadlink-with-size, areadlinkat-with-size, xgethostname, xgetdomainname
  by shrinking the result before returning it.
- In getcwd-lgpl and getcwd, shrinking is already done. But it may call
  realloc (P, SIZE) when the block allocated is already of size SIZE. It
  ought to be a no-op, but actually isn't on all platforms (on MSVC when
  SIZE is one of 8, 16, 32, ..., 16384).
- I'm not touching getdelim.c, because the calling convention of this function
  is made for calling getdelim() in a loop, and the buffer is meant to
  occasionally grow, not constantly grow and shrink and grow shrink ...


>From eb76defb19b3cc01e12d77d8cc96d402b9b5097d Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 6 Jul 2019 00:39:07 +0200
Subject: [PATCH 1/5] areadlink-with-size: Don't return an excessive memory
 allocation.

Reported by Andreas Dilger <adil...@whamcloud.com>.

* lib/areadlink-with-size.c (areadlink_with_size): Shrink the buffer
before returning it.
---
 ChangeLog                 | 7 +++++++
 lib/areadlink-with-size.c | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index d6209ef..c0ee6ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2019-07-05  Bruno Haible  <br...@clisp.org>
+
+	areadlink-with-size: Don't return an excessive memory allocation.
+	Reported by Andreas Dilger <adil...@whamcloud.com>.
+	* lib/areadlink-with-size.c (areadlink_with_size): Shrink the buffer
+	before returning it.
+
 2019-07-03  Bruno Haible  <br...@clisp.org>
 
 	renameatu: Fix test failure on MSVC.
diff --git a/lib/areadlink-with-size.c b/lib/areadlink-with-size.c
index eacad3f..364cc08 100644
--- a/lib/areadlink-with-size.c
+++ b/lib/areadlink-with-size.c
@@ -87,6 +87,13 @@ areadlink_with_size (char const *file, size_t size)
       if (link_length < buf_size)
         {
           buffer[link_length] = 0;
+          /* Shrink BUFFER before returning it.  */
+          if (link_length + 1 < buf_size)
+            {
+              char *shrinked_buffer = realloc (buffer, link_length + 1);
+              if (shrinked_buffer != NULL)
+                buffer = shrinked_buffer;
+            }
           return buffer;
         }
 
-- 
2.7.4

>From 8f91b5cf3514d664289afaace0d6f832b9608f20 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 6 Jul 2019 00:40:34 +0200
Subject: [PATCH 2/5] areadlinkat-with-size: Don't return an excessive memory
 allocation.

* lib/areadlinkat-with-size.c (areadlinkat_with_size): Shrink the buffer
before returning it.
---
 ChangeLog                   | 6 ++++++
 lib/areadlinkat-with-size.c | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c0ee6ce..d091eb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-07-05  Bruno Haible  <br...@clisp.org>
 
+	areadlinkat-with-size: Don't return an excessive memory allocation.
+	* lib/areadlinkat-with-size.c (areadlinkat_with_size): Shrink the buffer
+	before returning it.
+
+2019-07-05  Bruno Haible  <br...@clisp.org>
+
 	areadlink-with-size: Don't return an excessive memory allocation.
 	Reported by Andreas Dilger <adil...@whamcloud.com>.
 	* lib/areadlink-with-size.c (areadlink_with_size): Shrink the buffer
diff --git a/lib/areadlinkat-with-size.c b/lib/areadlinkat-with-size.c
index ed00b98..5b2bccc 100644
--- a/lib/areadlinkat-with-size.c
+++ b/lib/areadlinkat-with-size.c
@@ -92,6 +92,13 @@ areadlinkat_with_size (int fd, char const *file, size_t size)
       if (link_length < buf_size)
         {
           buffer[link_length] = 0;
+          /* Shrink BUFFER before returning it.  */
+          if (link_length + 1 < buf_size)
+            {
+              char *shrinked_buffer = realloc (buffer, link_length + 1);
+              if (shrinked_buffer != NULL)
+                buffer = shrinked_buffer;
+            }
           return buffer;
         }
 
-- 
2.7.4

>From 98802d166215602a88988ae566259edf4f67efe8 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 6 Jul 2019 00:43:01 +0200
Subject: [PATCH 3/5] xgethostname: Don't return an excessive memory
 allocation.

* lib/xgethostname.c (xgethostname): Shrink the hostname buffer before
returning it.
---
 ChangeLog          |  6 ++++++
 lib/xgethostname.c | 11 +++++++++++
 2 files changed, 17 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index d091eb1..c8dd18a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-07-05  Bruno Haible  <br...@clisp.org>
 
+	xgethostname: Don't return an excessive memory allocation.
+	* lib/xgethostname.c (xgethostname): Shrink the hostname buffer before
+	returning it.
+
+2019-07-05  Bruno Haible  <br...@clisp.org>
+
 	areadlinkat-with-size: Don't return an excessive memory allocation.
 	* lib/areadlinkat-with-size.c (areadlinkat_with_size): Shrink the buffer
 	before returning it.
diff --git a/lib/xgethostname.c b/lib/xgethostname.c
index eba34b8..4bcb00f 100644
--- a/lib/xgethostname.c
+++ b/lib/xgethostname.c
@@ -70,5 +70,16 @@ xgethostname (void)
         }
     }
 
+  /* Shrink HOSTNAME before returning it.  */
+  {
+    size_t actual_size = strlen (hostname) + 1;
+    if (actual_size < size)
+      {
+        char *shrinked_hostname = realloc (hostname, actual_size);
+        if (shrinked_hostname != NULL)
+          hostname = shrinked_hostname;
+      }
+  }
+
   return hostname;
 }
-- 
2.7.4

>From ac7390ac0884d155d3adc9d0f992413adcaaff87 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 6 Jul 2019 00:43:59 +0200
Subject: [PATCH 4/5] xgetdomainname: Don't return an excessive memory
 allocation.

* lib/xgetdomainname.c (xgetdomainname): Shrink the domainname buffer
before returning it.
---
 ChangeLog            |  6 ++++++
 lib/xgetdomainname.c | 11 +++++++++++
 2 files changed, 17 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c8dd18a..1f5f18b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-07-05  Bruno Haible  <br...@clisp.org>
 
+	xgetdomainname: Don't return an excessive memory allocation.
+	* lib/xgetdomainname.c (xgetdomainname): Shrink the domainname buffer
+	before returning it.
+
+2019-07-05  Bruno Haible  <br...@clisp.org>
+
 	xgethostname: Don't return an excessive memory allocation.
 	* lib/xgethostname.c (xgethostname): Shrink the hostname buffer before
 	returning it.
diff --git a/lib/xgetdomainname.c b/lib/xgetdomainname.c
index 2f59008..65df990 100644
--- a/lib/xgetdomainname.c
+++ b/lib/xgetdomainname.c
@@ -73,5 +73,16 @@ xgetdomainname (void)
       domainname = xrealloc (domainname, size);
     }
 
+  /* Shrink DOMAINNAME before returning it.  */
+  {
+    size_t actual_size = strlen (domainname) + 1;
+    if (actual_size < size)
+      {
+        char *shrinked_domainname = realloc (domainname, actual_size);
+        if (shrinked_domainname != NULL)
+          domainname = shrinked_domainname;
+      }
+  }
+
   return domainname;
 }
-- 
2.7.4

>From d44241344e8455c59ea04440706cfaf72862c404 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 6 Jul 2019 00:47:12 +0200
Subject: [PATCH 5/5] getcwd-lgpl, getcwd: Don't call realloc when it is
 pointless.

* lib/getcwd-lgpl.c (rpl_getcwd): Don't call realloc if the result's
needed size is equal to the allocated size.
* lib/getcwd.c (__getcwd): Likewise.
---
 ChangeLog         |  7 +++++++
 lib/getcwd-lgpl.c | 13 +++++++++----
 lib/getcwd.c      |  2 +-
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1f5f18b..98d5531 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2019-07-05  Bruno Haible  <br...@clisp.org>
 
+	getcwd-lgpl, getcwd: Don't call realloc when it is pointless.
+	* lib/getcwd-lgpl.c (rpl_getcwd): Don't call realloc if the result's
+	needed size is equal to the allocated size.
+	* lib/getcwd.c (__getcwd): Likewise.
+
+2019-07-05  Bruno Haible  <br...@clisp.org>
+
 	xgetdomainname: Don't return an excessive memory allocation.
 	* lib/xgetdomainname.c (xgetdomainname): Shrink the domainname buffer
 	before returning it.
diff --git a/lib/getcwd-lgpl.c b/lib/getcwd-lgpl.c
index b224cfc..1eaac78 100644
--- a/lib/getcwd-lgpl.c
+++ b/lib/getcwd-lgpl.c
@@ -115,10 +115,15 @@ rpl_getcwd (char *buf, size_t size)
     }
   else
     {
-      /* Trim to fit, if possible.  */
-      result = realloc (buf, strlen (buf) + 1);
-      if (!result)
-        result = buf;
+      /* Here result == buf.  */
+      /* Shrink result before returning it.  */
+      size_t actual_size = strlen (result) + 1;
+      if (actual_size < size)
+        {
+          char *shrinked_result = realloc (result, actual_size);
+          if (shrinked_result != NULL)
+            result = shrinked_result;
+        }
     }
   return result;
 }
diff --git a/lib/getcwd.c b/lib/getcwd.c
index 8f15f56..bf87809 100644
--- a/lib/getcwd.c
+++ b/lib/getcwd.c
@@ -443,7 +443,7 @@ __getcwd (char *buf, size_t size)
 
   if (size == 0)
     /* Ensure that the buffer is only as large as necessary.  */
-    buf = realloc (dir, used);
+    buf = (used < allocated ? realloc (dir, used) : dir);
 
   if (buf == NULL)
     /* Either buf was NULL all along, or 'realloc' failed but
-- 
2.7.4

Reply via email to