lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHk-=wiy=JOAWvSLwPq-jHPBfq8EX5NjVkEoh+RUMZbVn+GuOg@mail.gmail.com>
Date:   Wed, 6 Sep 2023 16:16:52 -0700
From:   Linus Torvalds <torvalds@...ux-foundation.org>
To:     Arnaldo Carvalho de Melo <acme@...nel.org>
Cc:     Kent Overstreet <kent.overstreet@...ux.dev>,
        linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
        linux-bcachefs@...r.kernel.org
Subject: Re: [GIT PULL] bcachefs

On Wed, 6 Sept 2023 at 14:55, Arnaldo Carvalho de Melo <acme@...nel.org> wrote:
>
> > I don't think gcc ever uses less than that (ie while a six_lock_type
> > could fit in two bits, it's still going to be considered at least a
> > 8-bit value in practice).
>
> There are some cases where people stuff the enum into a bitfield, but
> no, no simple type.

Note that I am talking about the types gcc uses natively.

To show what I'm talking about, build this (silly) code that has some
of the same enum types that bcachefs has:

    #include <stdio.h>

    enum enum1 {
        val1 = 0,
        val2 = 1,
        val3 = 2,
    };

    enum enum2 {
        num1 = -1,
        num2 = 0,
        num3 = 1,
        num4 = 2,
    };

    int main(int argc, char **argv)
    {
        printf("%d %d (%zu %zu)\n",
                (enum enum1) num1,
                (enum enum1) num1 == num1,
                sizeof(enum enum1),
                sizeof(enum enum2));
        return 0;
    }

and run it. On x86 with no special options, you should get something like this:

    -1 1 (4 4)

ie both types have a four-byte size, and casting 'num1' to 'enum
enum1' will in fact give you back -1, and will then compare equal to
num1 in the end.

Because both types are in practice just 'int'.

But now do the same with -fshort-enums, and you instead get

    255 0 (1 1)

because both types are just a single byte, and casting 'num1' to 'enum
enum1' will in fact result in 255 (because it's an _unsigned_ type),
and then comparing with the original num1 value will no longer compare
equal.

(But casting it then further back to 'enum enum2' will in fact result
in -1 again, because you're effectively casting it back to 'signed
char', and then 255 and -1 are in fact the same in that type).

End result: you can get some really unexpected behavior if you cast
enums to other types.

Which is, of course, exactly why the compiler is warning about the
comparison and about passing in the wrong type of enum.

Sadly, the compiler doesn't warn about the cast, so you can hide all
of this by just adding casts. That doesn't make it *right*, of course.

              Linus

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ