Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20181110175932.GA15979@voyager>
Date: Sat, 10 Nov 2018 18:59:32 +0100
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Subject: Re: [PATCH] Fix many compiler warnings

On Sat, Nov 10, 2018 at 05:48:23PM +0100, Sedrubal wrote:
> Hello,
> 
> I'm building musl for aarch64 with clang and get many compiler warnings
> (mostly Wbitwise-op-parentheses, Wshift-op-parentheses and Wlogical-op-parentheses).
> I tried to fix them (and I hope, I did not introduce new bugs).
> 

Well, hope belongs in the church. Whether or not you introduced bugs is
a thing you can test for. There is libc-test.

I don't know Rich's position on warnings, but my understanding was he
only cares about some of them. Writing code warning-free on multiple
platforms with multiple compilers is damn near impossible, anyway. (E.g.
take the following snippet:

switch (x)
{
    case foo:
        return other_func();
        break;
}

At work I have a compiler that will complain about the unreachable
break. If I deleted it I have another compiler (and a company directive)
warning that I have a case-statement that is not terminated with a
break.)

> 
> diff --git a/include/byteswap.h b/include/byteswap.h
> index 00b9df3c..f2dbb912 100644
> --- a/include/byteswap.h
> +++ b/include/byteswap.h
> @@ -11,12 +11,12 @@ static __inline uint16_t __bswap_16(uint16_t __x)
>  
>  static __inline uint32_t __bswap_32(uint32_t __x)
>  {
> -	return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24;
> +	return __x>>24 | __x>>(8&0xff00) | __x<<(8&0xff0000) | __x<<24;
>  }
>  

That's erroneous and you can actually see that pretty easily: The part
in the parentheses must always be zero. Could that possibly have been
the intention? No. (And this change fixed a warning? Shows what those
are worth!)

I guess the following will do the trick:

return (__x>>24) | (__x>>8 & 0xff00) | (__x<<8 & 0xff0000) | (__x<<24);

>  static __inline uint64_t __bswap_64(uint64_t __x)
>  {
> -	return __bswap_32(__x)+0ULL<<32 | __bswap_32(__x>>32);
> +	return (__bswap_32(__x)+0ULL)<<32 | __bswap_32(__x>>32);
>  }
>  
>  #define bswap_16(x) __bswap_16(x)
> diff --git a/include/endian.h b/include/endian.h
> index 1bd44451..6957fad3 100644
> --- a/include/endian.h
> +++ b/include/endian.h
> @@ -24,17 +24,17 @@
>  
>  static __inline uint16_t __bswap16(uint16_t __x)
>  {
> -	return __x<<8 | __x>>8;
> +	return (__x << 8) | (__x >> 8);
>  }
>  
>  static __inline uint32_t __bswap32(uint32_t __x)
>  {
> -	return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24;
> +	return (__x>>24) | ((__x>>8)&0xff00) | ((__x<<8)&0xff0000) | (__x<<24);
>  }
>  

You did it correctly here. The why the error above?

> diff --git a/src/locale/__mo_lookup.c b/src/locale/__mo_lookup.c
> index d18ab774..8750fd2c 100644
> --- a/src/locale/__mo_lookup.c
> +++ b/src/locale/__mo_lookup.c
> @@ -3,7 +3,7 @@
>  
>  static inline uint32_t swapc(uint32_t x, int c)
>  {
> -	return c ? x>>24 | x>>8&0xff00 | x<<8&0xff0000 | x<<24 : x;
> +	return c ? x>>24 | x>>(8&0xff00) | x<<(8&0xff0000) | x<<24 : x;
>  }
>  

Again, as above.

> diff --git a/src/locale/dcngettext.c b/src/locale/dcngettext.c
> index 8b891d00..39c0b191 100644
> --- a/src/locale/dcngettext.c
> +++ b/src/locale/dcngettext.c
> @@ -176,7 +176,7 @@ notrans:
>  			snprintf(name, sizeof name, "%s/%.*s%.*s/%s/%s.mo\0",
>  				dirname, (int)loclen, locname,
>  				(int)alt_modlen, modname, catname, domainname);
> -			if (map = __map_file(name, &map_size)) break;
> +			if ((map = __map_file(name, &map_size))) break;
>  

Actually, why is there an if-condition assignment here? I've done that
in the past, but only in complex conditions, not simple ones like this.
Wouldn't

    map = __map_file(name, &map_size);
    if (map) break;

be better style here? I'm not against assigning in conditions in
general, but it should serve a purpose. "while ((de = readdir(d)))" has
such a purpose, but that is a while-condition.

> diff --git a/src/locale/iconv.c b/src/locale/iconv.c
> index 3047c27b..d189f598 100644
> --- a/src/locale/iconv.c
> +++ b/src/locale/iconv.c
> @@ -181,7 +181,7 @@ static void put_16(unsigned char *s, unsigned c, int e)
>  static unsigned get_32(const unsigned char *s, int e)
>  {
>  	e &= 3;
> -	return s[e]+0U<<24 | s[e^1]<<16 | s[e^2]<<8 | s[e^3];
> +	return (s[e]+0U)<<24 | s[e^1]<<16 | s[e^2]<<8 | s[e^3];
>  }
>  

Wait, I'm confused again. Why is it necessary to convert the first
dereference of s to unsigned int, but not the others?

>  static void put_32(unsigned char *s, unsigned c, int e)
> @@ -201,7 +201,7 @@ static unsigned legacy_map(const unsigned char *map, unsigned c)
>  {
>  	if (c < 4*map[-1]) return c;
>  	unsigned x = c - 4*map[-1];
> -	x = map[x*5/4]>>2*x%8 | map[x*5/4+1]<<8-2*x%8 & 1023;
> +	x = (map[x*5/4]>>(2*x%8)) | ((map[x*5/4+1]<<(8-2*x%8)) & 1023);
>  	return x < 256 ? x : legacy_chars[x-256];
>  }
>  

I've stared at the old line for five minutes now, and I still don't know
what it does. As such I can't evaluate the consistency of the new
version. What were you thinking when you wrote that line, Rich?

Let's see here... bitshift binds less strongly than arithmetic, and
bitlogic binds even less strongly than that. So mechanically, the new
line is correct. I still don't know what it does.

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.