Announcement

Collapse
No announcement yet.

Proposed GCC 12 Security Option Would Auto Initialize Automatic Variables

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by carewolf View Post
    Of all the potential problem in C++, the one I have never has any issues with, is problems due to uninitialized variables. Is it something other people see a lot?
    There are cases where you don't have a meaningful value, at the point of definition. So, you're faced with a dilemma of either zero-initializing it and preventing the compiler from warning you of possible use before it's been properly-assigned, or hoping to benefit from such warnings while incurring the risk that the compiler doesn't catch it and you end up with some unpredictable behavior at runtime. Since I try to write my code semantically, I'm somewhat allergic to using bogus initializers, just for the sake of initializing to something.

    C++11 lambdas enable a style where you can often avoid this situation, but I sometimes wonder if such lambdas could incur runtime overhead, and it can confuse people reading your code who aren't used to that style. It does feel like a slight abuse of the lambda mechanism, but still preferable to bogus initializers.

    Comment


    • #22
      I just hope the compiler emits something that tools like valgrind can use to track when such variables get used before they've been properly assigned. Then, I'd be 100% onboard with this feature.

      Comment


      • #23
        Originally posted by arQon View Post
        As several others have already said: use -Wuninitialized and treat warnings as errors. Fix your damn code!
        If only it were that simple!

        Originally posted by arQon View Post
        IOW, this is a *terrible* idea.
        It's not mutually-exclusive, is it? I guarantee there are cases where -Wuninitialized will give a false-negative! Why not wear a belt and suspenders?
        Last edited by coder; 25 February 2021, 03:35 AM.

        Comment


        • #24
          Originally posted by tinko View Post
          Wouldn't it preferable, for a security-enhanced build-setting, to use -Wuninitialized and make it an error?
          Anyone who thinks this is an equivalent solution hasn't used -Wuninitialized very much, or thought about it very hard. Determining whether a variable is used before/without being initialized isn't always practical, either for lack of visibility or due to sheer computational complexity.

          This is why they added -Wmaybe-uninitialized, but that has too many false-positives, in my experience.
          Last edited by coder; 25 February 2021, 03:33 AM.

          Comment


          • #25
            Originally posted by intelfx View Post
            I'm quite eager to see someone's code blowing up some time down the line due to using uninitialized reads as a source of randomness
            That's what /dev/urandom is for. /dev/random is obviously better, but can be much slower (and unpredictably so). So, urandom is preferred when you just need something sorta random and it's not being used for security purposes.

            Comment


            • #26
              Originally posted by coder View Post
              There are cases where you don't have a meaningful value, at the point of definition. So, you're faced with a dilemma of either zero-initializing it and preventing the compiler from warning you of possible use before it's been properly-assigned, or hoping to benefit from such warnings while incurring the risk that the compiler doesn't catch it and you end up with some unpredictable behavior at runtime. Since I try to write my code semantically, I'm somewhat allergic to using bogus initializers, just for the sake of initializing to something.

              C++11 lambdas enable a style where you can often avoid this situation, but I sometimes wonder if such lambdas could incur runtime overhead, and it can confuse people reading your code who aren't used to that style. It does feel like a slight abuse of the lambda mechanism, but still preferable to bogus initializers.
              Me too. That is the weird thing. While I have never seen a bug from uninitialized value, I have fixed thousands of false-flag warnings. And I know if the compiler mistakingly thinks the value could be used uninitialized it isn't smart enough to optimize the initialization away since it is always set before being used. Especially gcc with -Og which apparently has a bad combo of abilities making -Wuninitialized both active and not working very well.

              Comment


              • #27
                Originally posted by ermo View Post
                I can't imagine that an Oracle engineer *wouldn't* have considered the relevant alternatives and tradeoffs, given that it seems to be a company which is pretty focused on their bottom line and extracting as much revenue from its products and customers as possible.
                Just because upper management and the lawyers like money a lot doesn't mean they'll always demand high standards of engineers, and just demanding high standards doesn't mean you meet them.

                Comment


                • #28
                  Originally posted by coder View Post
                  Anyone who thinks this is an equivalent solution hasn't used -Wuninitialized very much, or thought about it very hard. Determining whether a variable is used before/without being initialized isn't always practical, either for lack of visibility or due to sheer computational complexity.
                  I think I've seen clang-tidy highlighting false positive cases of uninitialized variables, but oddly only when used as a plugin in Visual Studio, while the same doesn't happen when used in a Linux CMake build of the same (cross-platform) code.

                  However, this patch only applies to local variables which are usually declared immediately before their use, where -Wuninitialized shouldn't really fail.




                  Comment


                  • #29
                    Originally posted by arQon View Post
                    As several others have already said: use -Wuninitialized and treat warnings as errors. Fix your damn code!

                    IOW, this is a *terrible* idea. Except... the one thing that may well save it from being shot down right away is the usual "legacy codebase" argument.
                    But in practical terms, anyone who has a legacy codebase that they're still compiling without caring about the code quality (oh wait: it WAS an oracle dev suggesting this, right? :P) in the first place seems also unlikely to be paying enough attention to add this flag anyway, I expect.
                    "-Werror=uninitialized" is the flag you want.

                    There is some justification in having a flag to make uninitialised auto variables zero initialised. It could occasionally help deal with old, broken code that no one wants to fix, but which "works" with older compilers and fails with newer ones. But even then, it should force a -Wuninitialized warning. It could be viewed as a "help people who don't understand the subtleties of C" flag, along with "-fno-strict-aliasing" and "-fwrapv".

                    Initializing to a pattern to try to cause crashes as an aid to debugging is insane, when gcc already has a vastly better way of finding these problems - the -Wuninitialised and -Wmaybe-uninitialised flags.

                    Comment


                    • #30
                      Originally posted by wkleunen View Post
                      It is not all local variables. But only plain old data: like int, float, or a pointer. So objects of classes are always initialized.

                      Having programmed a lot of C++, i think it is a good idea to have some default initialized value. Programmers expect that is initialized to zero, and many times in practice, it is, but it is not defined behaviour. The performance overhead is non-existent, it is just writing some default value. With todays CPU superscalar, you won't notice the performance difference. And the value of variables not initialized is "undefined". If you initialize to zero, this is also "undefined". If existing code breaks, it was broken already before.
                      Objects of class types are initialised by recursively initialising subobjects, using constructors and initialisers. If you get down to POD data that has no initialisation (such as an "int" field in a class without a constructor), that is left uninitialised just like a plain "int".

                      Having programmed a lot of C and C++, I know that having a default initialised value is a truly terrible idea. Programmers who know how these languages work do not expect them to be initialised to zero - and having inexperienced programmers working alone is also a terrible idea. (We all start out as inexperienced - but we need help to learn and people to check our code, not crutches from tools that encourage bad habits.) The problem with pointless initialisation is not one of performance (though some 99.9% of processors shipped are not superscaler). The problem is it stops the compiler telling you when you have made a mistake and read an uninitialised variable. Default initialisation does not make the broken code correct - it merely changes it from undefined behaviour wrong code to defined behaviour but still wrong code that is now harder to spot.

                      And if you are structuring your code properly, rather than in pre-C99 style, the whole issue is usually moot - you don't define your local variables until you have a value for them, so default initialisation is of no use.

                      Oh, and it does not quite make sense to say an uninitialised object has value "undefined". The value is "indeterminate" (basically meaning it can be any pattern of bits that fits within the storage space of the object). Attempting to use this indeterminate value is undefined behaviour (which is always bad). If the compiler guarantees (such as via an option) that all auto storage variables are initialised to zero, then it is not an indeterminate value, and their use is not undefined behaviour - the behaviour is very clearly defined. (But you are entirely correct that if this new switch "breaks" code, the code was broken from before.)

                      Comment

                      Working...
                      X