bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* New function xpalloc in module xalloc
@ 2021-04-04  6:17 Marc Nieper-Wißkirchen
  2021-04-04  6:23 ` Jeffrey Walton
  2021-04-06  3:19 ` Paul Eggert
  0 siblings, 2 replies; 8+ messages in thread
From: Marc Nieper-Wißkirchen @ 2021-04-04  6:17 UTC (permalink / raw)
  To: bug-gnulib

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

GCC prints the following warning when compiling the new code:

lib/xmalloc.c: In function 'xpalloc':
lib/xmalloc.c:132:64: warning: comparison of integer expressions of
different signedness: 'long unsigned int' and 'idx_t' {aka 'long int'}
[-Wsign-compare]
  132 |     = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX <
nbytes)

If I understand the error message correctly, it is because 'nbytes' is a
signed type while SIZE_MAX is unsigned.

Does the comparison make any sense, by the way?

Thanks for investigating,

Marc

[-- Attachment #2: Type: text/html, Size: 1323 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-04  6:17 New function xpalloc in module xalloc Marc Nieper-Wißkirchen
@ 2021-04-04  6:23 ` Jeffrey Walton
  2021-04-04  6:43   ` Marc Nieper-Wißkirchen
  2021-04-06  3:19 ` Paul Eggert
  1 sibling, 1 reply; 8+ messages in thread
From: Jeffrey Walton @ 2021-04-04  6:23 UTC (permalink / raw)
  To: Marc Nieper-Wißkirchen; +Cc: bug-gnulib@gnu.org List

On Sun, Apr 4, 2021 at 2:17 AM Marc Nieper-Wißkirchen
<marc.nieper+gnu@gmail.com> wrote:
>
> GCC prints the following warning when compiling the new code:
>
> lib/xmalloc.c: In function 'xpalloc':
> lib/xmalloc.c:132:64: warning: comparison of integer expressions of different signedness: 'long unsigned int' and 'idx_t' {aka 'long int'} [-Wsign-compare]
>   132 |     = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
>
> If I understand the error message correctly, it is because 'nbytes' is a signed type while SIZE_MAX is unsigned.
>
> Does the comparison make any sense, by the way?

Only for positive integers.

If idx_t is negative, like -1, then -1 will be promoted to an unsigned
type and then -1 > 0.

Jeff


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-04  6:23 ` Jeffrey Walton
@ 2021-04-04  6:43   ` Marc Nieper-Wißkirchen
  0 siblings, 0 replies; 8+ messages in thread
From: Marc Nieper-Wißkirchen @ 2021-04-04  6:43 UTC (permalink / raw)
  To: noloader; +Cc: Marc Nieper-Wißkirchen, bug-gnulib@gnu.org List

[-- Attachment #1: Type: text/plain, Size: 1212 bytes --]

SIZE_MAX could be defined as -1 promoted to an unsigned type, meaning that
the unsigned comparison would always yield false. Or am I missing something?

In any case, if the promotion is what is intended, 'nbytes' should be
probably replaced with '(size_t) nbytes' to silence the warning and to make
it explicit.


Am So., 4. Apr. 2021 um 08:24 Uhr schrieb Jeffrey Walton <noloader@gmail.com
>:

> On Sun, Apr 4, 2021 at 2:17 AM Marc Nieper-Wißkirchen
> <marc.nieper+gnu@gmail.com> wrote:
> >
> > GCC prints the following warning when compiling the new code:
> >
> > lib/xmalloc.c: In function 'xpalloc':
> > lib/xmalloc.c:132:64: warning: comparison of integer expressions of
> different signedness: 'long unsigned int' and 'idx_t' {aka 'long int'}
> [-Wsign-compare]
> >   132 |     = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX <
> nbytes)
> >
> > If I understand the error message correctly, it is because 'nbytes' is a
> signed type while SIZE_MAX is unsigned.
> >
> > Does the comparison make any sense, by the way?
>
> Only for positive integers.
>
> If idx_t is negative, like -1, then -1 will be promoted to an unsigned
> type and then -1 > 0.
>
> Jeff
>

[-- Attachment #2: Type: text/html, Size: 1934 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-04  6:17 New function xpalloc in module xalloc Marc Nieper-Wißkirchen
  2021-04-04  6:23 ` Jeffrey Walton
@ 2021-04-06  3:19 ` Paul Eggert
  2021-04-06  6:48   ` Marc Nieper-Wißkirchen
  1 sibling, 1 reply; 8+ messages in thread
From: Paul Eggert @ 2021-04-06  3:19 UTC (permalink / raw)
  To: Marc Nieper-Wißkirchen; +Cc: Gnulib bugs

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

On 4/3/21 11:17 PM, Marc Nieper-Wißkirchen wrote:
> Does the comparison make any sense, by the way?

Yes, although it's needed only on unusual (and these days perhaps 
theoretical?) platforms where SIZE_MAX < PTRDIFF_MAX.

I hadn't noticed the issue, as the projects I contribute to (coreutils, 
etc.) compile with -Wno-sign-compare because gcc -Wsign-compare has too 
many false alarms.

I prefer to avoid casts merely to pacify GCC (as casts are too 
error-prone), so I installed the attached. I hope it works for you. (If 
not, perhaps you can use -Wno-sign-compare too....)

This underscores the fact that the xalloc module should use idx_t 
instead of size_t pretty much everywhere. If xrealloc's size arg were of 
idx_t we wouldn't need any of this hacking. I realize that replacing 
size_t with idx_t is an incompatible change to xalloc's API, but it's 
time callers started using signed instead of unsigned byte counts as 
that helps avoid and/or catch integer-overflow errors better. I'll add 
that to my list of things to do for Gnulib.

[-- Attachment #2: 0001-xalloc-try-to-pacify-gcc-Wsign-compare.patch --]
[-- Type: text/x-patch, Size: 2582 bytes --]

From 06931a1f5fc04cf4e3585408fa10f79a745b3099 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 5 Apr 2021 20:08:27 -0700
Subject: [PATCH] xalloc: try to pacify gcc -Wsign-compare
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Marc Nieper-Wißkirchen in:
https://lists.gnu.org/r/bug-gnulib/2021-04/msg00034.html
* lib/xmalloc.c (xpalloc): For odd platforms where SIZE_MAX < IDX_MAX,
use a tricky destination for INT_MULTIPLY_WRAPV instead of an
explicit comparison to SIZE_MAX.  This should be more likely to
pacify gcc -Wsign-compare.
---
 ChangeLog     | 10 ++++++++++
 lib/xmalloc.c | 13 +++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 81d3aab73..f3cca1ab2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2021-04-05  Paul Eggert  <eggert@cs.ucla.edu>
+
+	xalloc: try to pacify gcc -Wsign-compare
+	Problem reported by Marc Nieper-Wißkirchen in:
+	https://lists.gnu.org/r/bug-gnulib/2021-04/msg00034.html
+	* lib/xmalloc.c (xpalloc): For odd platforms where SIZE_MAX < IDX_MAX,
+	use a tricky destination for INT_MULTIPLY_WRAPV instead of an
+	explicit comparison to SIZE_MAX.  This should be more likely to
+	pacify gcc -Wsign-compare.
+
 2021-04-05  Marc Nieper-Wißkirchen  <marc@nieper-wisskirchen.de>
 
 	hamt: Fix coding errors.
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
index faeccacc9..4a6589571 100644
--- a/lib/xmalloc.c
+++ b/lib/xmalloc.c
@@ -122,14 +122,23 @@ xpalloc (void *pa, idx_t *nitems, idx_t nitems_incr_min,
      Adjust the growth according to three constraints: NITEMS_INCR_MIN,
      NITEMS_MAX, and what the C language can represent safely.  */
 
-  idx_t n, nbytes;
+  idx_t n;
   if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
     n = IDX_MAX;
   if (0 <= nitems_max && nitems_max < n)
     n = nitems_max;
 
+  /* NBYTES is of a type suitable for holding the count of bytes in an object.
+     This is typically idx_t, but it should be size_t on (theoretical?)
+     platforms where SIZE_MAX < IDX_MAX so xpalloc does not pass
+     values greater than SIZE_MAX to xrealloc.  */
+#if IDX_MAX <= SIZE_MAX
+  idx_t nbytes;
+#else
+  size_t nbytes;
+#endif
   idx_t adjusted_nbytes
-    = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
+    = (INT_MULTIPLY_WRAPV (n, item_size, &nbytes)
        ? MIN (IDX_MAX, SIZE_MAX)
        : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
   if (adjusted_nbytes)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-06  3:19 ` Paul Eggert
@ 2021-04-06  6:48   ` Marc Nieper-Wißkirchen
  2021-04-06 19:05     ` Paul Eggert
  0 siblings, 1 reply; 8+ messages in thread
From: Marc Nieper-Wißkirchen @ 2021-04-06  6:48 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Marc Nieper-Wißkirchen, Gnulib bugs

[-- Attachment #1: Type: text/plain, Size: 1898 bytes --]

Hi Paul,

Am Di., 6. Apr. 2021 um 05:19 Uhr schrieb Paul Eggert <eggert@cs.ucla.edu>:

> On 4/3/21 11:17 PM, Marc Nieper-Wißkirchen wrote:
> > Does the comparison make any sense, by the way?
>
> Yes, although it's needed only on unusual (and these days perhaps
> theoretical?) platforms where SIZE_MAX < PTRDIFF_MAX.
>

Ah, okay. I didn't think of this possibility.


> I hadn't noticed the issue, as the projects I contribute to (coreutils,
> etc.) compile with -Wno-sign-compare because gcc -Wsign-compare has too
> many false alarms.
>
> I prefer to avoid casts merely to pacify GCC (as casts are too
> error-prone), so I installed the attached. I hope it works for you. (If
> not, perhaps you can use -Wno-sign-compare too....)
>

The fix works for me. Thank you very much! IMO, it's much better than
asking to compile with "-Wno-sign-compare' because this can (like type
casts) silence other, non-false positive warnings.

Speaking of type casts, I don't think they would have been bad here because
they would document exactly what was going on here. By writing

SIZE_MAX < (uintmax_t) nbytes

the otherwise implicit type conversion would have been made explicit and
using 'uintmax_t' also documents that it is expected that the width of
'nbytes' can be greater than the width of 'size_t'.


> This underscores the fact that the xalloc module should use idx_t
> instead of size_t pretty much everywhere. If xrealloc's size arg were of
> idx_t we wouldn't need any of this hacking. I realize that replacing
> size_t with idx_t is an incompatible change to xalloc's API, but it's
> time callers started using signed instead of unsigned byte counts as
> that helps avoid and/or catch integer-overflow errors better. I'll add
> that to my list of things to do for Gnulib.
>

The philosophy about idx_t could be worth an entry in the manual.

Marc

[-- Attachment #2: Type: text/html, Size: 3434 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-06  6:48   ` Marc Nieper-Wißkirchen
@ 2021-04-06 19:05     ` Paul Eggert
  2021-04-06 19:23       ` Marc Nieper-Wißkirchen
  0 siblings, 1 reply; 8+ messages in thread
From: Paul Eggert @ 2021-04-06 19:05 UTC (permalink / raw)
  To: Marc Nieper-Wißkirchen; +Cc: Gnulib bugs

On 4/5/21 11:48 PM, Marc Nieper-Wißkirchen wrote:
> SIZE_MAX < (uintmax_t) nbytes

Eeuuw! That's a cure worse than the disease. Among other things, there 
is no guarantee that PTRDIFF_MAX <= UINTMAX_MAX so in theory the 
comparison could go completely awry with a sufficiently-large NBYTES.

"Don't use casts." Words to live by.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-06 19:05     ` Paul Eggert
@ 2021-04-06 19:23       ` Marc Nieper-Wißkirchen
  2021-04-06 20:07         ` Paul Eggert
  0 siblings, 1 reply; 8+ messages in thread
From: Marc Nieper-Wißkirchen @ 2021-04-06 19:23 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Marc Nieper-Wißkirchen, Gnulib bugs

[-- Attachment #1: Type: text/plain, Size: 691 bytes --]

Am Di., 6. Apr. 2021 um 21:05 Uhr schrieb Paul Eggert <eggert@cs.ucla.edu>:

> On 4/5/21 11:48 PM, Marc Nieper-Wißkirchen wrote:
> > SIZE_MAX < (uintmax_t) nbytes
>
> Eeuuw! That's a cure worse than the disease. Among other things, there
> is no guarantee that PTRDIFF_MAX <= UINTMAX_MAX so in theory the
> comparison could go completely awry with a sufficiently-large NBYTES.
>

I checked the ISO C18 standard before I wrote this. :) In 6.2.5 it says
that for every signed type there is an unsigned type of the same width.
Given the definitions of INTMAX_MAX and UINTMAX_MAX, I then concluded

PTRDIFF_MAX <= INTMAX_MAX <= UINTMAX_MAX.

Where is the flaw in my reasoning?

[-- Attachment #2: Type: text/html, Size: 1404 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: New function xpalloc in module xalloc
  2021-04-06 19:23       ` Marc Nieper-Wißkirchen
@ 2021-04-06 20:07         ` Paul Eggert
  0 siblings, 0 replies; 8+ messages in thread
From: Paul Eggert @ 2021-04-06 20:07 UTC (permalink / raw)
  To: Marc Nieper-Wißkirchen; +Cc: Gnulib bugs

On 4/6/21 12:23 PM, Marc Nieper-Wißkirchen wrote:
> Where is the flaw in my reasoning?

Oh, you're right; any nonnegative signed integer value will fit into 
uintmax_t. (Perhaps this wasn't always true in older standards, but it's 
true of the recent C standard.)

So that cast should work. Still, I wouldn't use a cast; I'd assign the 
integer to an uintmax_t local value, and use that.

And anyway, for this particular case widening to uintmax_t is not 
necessary; it complicates the code and can make it less efficient on 
some platforms by forcing an unnecessary conversion at runtime. So let's 
not do that.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-04-06 20:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-04  6:17 New function xpalloc in module xalloc Marc Nieper-Wißkirchen
2021-04-04  6:23 ` Jeffrey Walton
2021-04-04  6:43   ` Marc Nieper-Wißkirchen
2021-04-06  3:19 ` Paul Eggert
2021-04-06  6:48   ` Marc Nieper-Wißkirchen
2021-04-06 19:05     ` Paul Eggert
2021-04-06 19:23       ` Marc Nieper-Wißkirchen
2021-04-06 20:07         ` Paul Eggert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).