Re: Uninitialized variables and F37

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 2022-01-22 at 20:49 +0000, Richard W.M. Jones wrote:
> On Sat, Jan 22, 2022 at 03:00:14PM -0500, Steve Grubb wrote:
> > On Saturday, January 22, 2022 6:36:01 AM EST Vitaly Zaitsev via
> > devel wrote:
> > > On 21/01/2022 19:04, Steve Grubb wrote:
> > > > Uninitialized variables are a big problem.
> > > 
> > > Yes, but as a package maintainer, I don't want to deal with
> > > dozens of
> > > crashes after this change.
> > 
> > As much as I don't want this to cause unnecessary work for anyone,
> > I also 
> > don't want to see preventable exploits happen. Nearly all major
> > software 
> > vendors are doing this.
> > 
> > I mentioned in the original proposal that I have a test program
> > with 8 test 
> > cases. This is it in case anyone wants to try it out:
> > 
> > #include <stdio.h>
> > 
> > struct test {
> >         int one;
> >         int two;
> > };
> > 
> > void func2(const struct test *t)
> > {
> >         if (t->one == 0)
> >                 printf("init func2\n");
> > 
> >         if (t->two == 0)  // Uninitialized 1
> >                 printf("uninit func2\n");
> > }
> > 
> > void func1(struct test *t)
> > {
> >         t->one = 1; // two is uninitialized
> >         func2(t);
> > }
> > 
> > int func3(int num)
> > {
> >         if (num) // Uninitialized 2
> >                 return num;
> >         else
> >                 return 0;
> > }
> > 
> > void func4(int *a, int max)
> > {
> >         int i;
> >         // skip the first
> >         for (i=1; i<max; i++)
> >                 a[i] = 0;
> > }
> > 
> > void func5(const int *a, int max)
> > {
> >         int i;
> >         for (i=0; i<max; i++) {
> >                 if (a[i]) // Uninitialized 3
> >                         printf("func5: %d\n", i);
> >         }
> > }
> > 
> > int func6(const int *num)
> > {
> >         if (*num) // Uninitialized 4
> >                 return *num;
> >         else
> >                 return 0;
> > }
> > 
> > int j;
> > int func7(void)
> > {
> >         return j;  // Uninitialized 5
> > }
> > 
> > void func8(const int *a, int max)
> > {
> >         int i;
> >         for (i=0; i<max; i++) {
> >                 if (a[i]) // Uninitialized 6
> >                         printf("func8: %d\n", i);
> >         }
> > }
> > 
> > enum {RED, AMBER, GREEN, BLACK};
> > 
> > int main(void)
> > {
> >         struct test t;
> >         int num;
> >         int arry[10];
> >         int go;
> >         int color = BLACK;
> > 
> >         func1(&t);
> >         func3(num);
> >         func4(arry, 10);
> >         func5(arry, 10);
> >         func6(&num);
> > 
> >         printf("num: %d\n", num); // Uninitialized 7
> >         printf("func7: %d\n", func7());
> >         arry[0] = func7(); // copy uninitiliazed j into arry[0]
> >         func8(arry, 10);
> > 
> >         switch (color) {
> >         case RED:
> >         case AMBER:
> >                 go = 0;
> >                 break;
> >         case GREEN:
> >                 go = 1;
> >                 break;
> >         }
> > 
> >         printf("go :%d\n", go); // Uninitialized 8
> > 
> >         return 0;
> > }
> > 
> > 
> > Detection results:
> > gcc11 : 0
> > gcc11+fanalyzer: 0
> > gcc12: 2
> > gcc12+fanalyzer: 3
> > cppcheck: 2   but describes different aspects of the same problems
> > gcc11+asan: 0
> > gcc11:+ubsan: 0
> > clang13: 1
> > valgrind+clang: 0
> > valgrind+gcc: 2
> > Flexelint: 1
> > splint: 2
> > 
> > The one surprising result is that valgrind's results differ by the
> > compiler 
> > choice.
> 
> valgrind seems to do better for me than described.  It spots errors
> in
> these places:
> 
>   test.c:13 (Uninitialised 1)
>   test.c:25 (Uninitialised 2)
>   test.c:43 (Uninitialised 3)
>   test.c:50 (Uninitialised 4)
>   test.c:87 (Uninitialized 7)
>   test.c:102 (Uninitialized 8)
> 
> So I'd say it's getting 6/8.
> 
> I did:
> 
>   $ gcc -g test.c -o test
>   $ valgrind ./test

Right. That is because:

return j;  // Uninitialized 5

Isn't actually use (it just returns) and j is an global variable, which
are already initialized to zero by default.

And so also this:

        arry[0] = func7(); // copy uninitiliazed j into arry[0]

Is actually assigning an initialized (zero) value.

So I would give valgrind a 6/6 (100%) score :)

If you compile with -O2 gcc will only leave 2 actual uses of
uninitialized values in the code, so valgrind can also only spot 2. The
compiler (correctly) determines all other code isn't actually used and
so optimizes it out.

Cheers,

Mark
_______________________________________________
devel mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxx
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/devel@xxxxxxxxxxxxxxxxxxxxxxx
Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Fedora Announce]     [Fedora Users]     [Fedora Kernel]     [Fedora Testing]     [Fedora Formulas]     [Fedora PHP Devel]     [Kernel Development]     [Fedora Legacy]     [Fedora Maintainers]     [Fedora Desktop]     [PAM]     [Red Hat Development]     [Gimp]     [Yosemite News]

  Powered by Linux