Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

False positive: Uninitialized value used after std::seed_seq::generate #40269

Open Quuxplusone opened 5 years ago

Quuxplusone commented 5 years ago
Bugzilla Link PR41299
Status NEW
Importance P enhancement
Reported by Alexander Grund (alexander.grund@tu-dresden.de)
Reported on 2019-03-29 05:25:35 -0700
Last modified on 2019-04-01 07:03:56 -0700
Version unspecified
Hardware PC Linux
CC alexfh@google.com, dcoughlin@apple.com, djasper@google.com, eugene.zelenko@gmail.com, klimek@google.com, llvm-bugs@lists.llvm.org
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also

I implemented a custom PRNG according to the standard which uses a 32-Bit value as the seed. Hence I've implemented the seed(seedSeq) function as follows:

{ unsigned seedVal; seedSeq.generate(&seedVal, (&seedVal) + 1); seed(seedVal); }

However clang-tidy warns about using an uninitialized value for the call to seed at the bottom.

Relevant output:

[...] /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.tcc:3279:4: note: Value assigned to 'r1' r1 = detail::mod<_Type, [...] /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.tcc:3290:4: note: Uninitialized value stored to 'seedVal' begin[(k + p) % n] += __r1;

There is nothing else that looks suspicious. My guess is that as clang-tidy cannot deduce that n = __end - __begin in this case equals one it messes up the rest.

Quuxplusone commented 5 years ago

Could you please provide full message with check name?

Quuxplusone commented 5 years ago
Sure:

clang-tidy-8 -p . -checks="-*,clang-analyzer-core.CallAndMessage" main.cpp
1 warning generated.
/home/alex/Schreibtisch/cmakeTest/main.cpp:10:5: warning: 1st function call
argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
    seed(seedVal);
    ^
/home/alex/Schreibtisch/cmakeTest/main.cpp:15:3: note: Calling
'MySeed<std::seed_seq>'
  MySeed(seedSeq);
  ^
/home/alex/Schreibtisch/cmakeTest/main.cpp:9:5: note: Calling
'seed_seq::generate'
    seedSeq.generate(&seedVal, (&seedVal) + 1);
    ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3257:7: note: Taking false
branch
      if (__begin == __end)
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3260:7: note: Calling
'fill<unsigned int *, unsigned int>'
      std::fill(__begin, __end, _Type(0x8b8b8b8bu));
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:731:21: note: Calling
'__niter_base<unsigned int *>'
      std::__fill_a(std::__niter_base(__first), std::__niter_base(__last),
                    ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:731:21: note: Returning
from '__niter_base<unsigned int *>'
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:731:7: note: Calling
'__fill_a<unsigned int *, unsigned int>'
      std::__fill_a(std::__niter_base(__first), std::__niter_base(__last),
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:695:7: note: Loop condition
is true.  Entering loop body
      for (; __first != __last; ++__first)
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:695:7: note: Loop condition
is false. Execution continues on line 695
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/stl_algobase.h:731:7: note: Returning from
'__fill_a<unsigned int *, unsigned int>'
      std::__fill_a(std::__niter_base(__first), std::__niter_base(__last),
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3260:7: note: Returning from
'fill<unsigned int *, unsigned int>'
      std::fill(__begin, __end, _Type(0x8b8b8b8bu));
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3264:27: note: Assuming '__n'
is >= 623
      const size_t __t = (__n >= 623) ? 11
                          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3264:26: note: '?' condition is
true
      const size_t __t = (__n >= 623) ? 11
                         ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3273:28: note: Assuming '__k'
is < '__m'
      for (size_t __k = 0; __k < __m; ++__k)
                           ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3273:7: note: Loop condition is
true.  Entering loop body
      for (size_t __k = 0; __k < __m; ++__k)
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3279:11: note: Calling
'__mod<unsigned int, 0, 1, 0>'
          __r1 = __detail::__mod<_Type,
                 ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:147:16: note: Calling
'_Mod::__calc'
      { return _Mod<_Tp, __m, __a, __c>::__calc(__x); }
               ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:137:4: note: '__res' initialized
here
          _Tp __res = __a * __x + __c;
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:138:4: note: Taking false branch
          if (__m)
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:140:4: note: Returning value
(loaded from '__res')
          return __res;
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:147:16: note: Returning from
'_Mod::__calc'
      { return _Mod<_Tp, __m, __a, __c>::__calc(__x); }
               ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.h:147:9: note: Returning value
      { return _Mod<_Tp, __m, __a, __c>::__calc(__x); }
        ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3279:11: note: Returning from
'__mod<unsigned int, 0, 1, 0>'
          __r1 = __detail::__mod<_Type,
                 ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3279:4: note: Value assigned to
'__r1'
          __r1 = __detail::__mod<_Type,
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3282:4: note: Taking true branch
          if (__k == 0)
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3290:4: note: Uninitialized
value stored to 'seedVal'
          __begin[(__k + __p) % __n] += __r1;
          ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3273:28: note: Assuming '__k'
is >= '__m'
      for (size_t __k = 0; __k < __m; ++__k)
                           ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3273:7: note: Loop condition is
false. Execution continues on line 3295
      for (size_t __k = 0; __k < __m; ++__k)
      ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3295:30: note: Assuming the
condition is false
      for (size_t __k = __m; __k < __m + __n; ++__k)
                             ^
/usr/bin/../lib/gcc/x86_64-linux-
gnu/8/../../../../include/c++/8/bits/random.tcc:3295:7: note: Loop condition is
false. Execution continues on line 3295
      for (size_t __k = __m; __k < __m + __n; ++__k)
      ^
/home/alex/Schreibtisch/cmakeTest/main.cpp:9:5: note: Returning from
'seed_seq::generate'
    seedSeq.generate(&seedVal, (&seedVal) + 1);
    ^
/home/alex/Schreibtisch/cmakeTest/main.cpp:10:5: note: 1st function call
argument is an uninitialized value
    seed(seedVal);

Input file:

#include <random>

extern void seed(unsigned);

template<class T_SeedSeq>
inline void MySeed(T_SeedSeq& seedSeq)
{
    unsigned seedVal;
    seedSeq.generate(&seedVal, (&seedVal) + 1);
    seed(seedVal);
}

int main(){
  std::seed_seq seedSeq({1,2,3});
  MySeed(seedSeq);
}
Quuxplusone commented 5 years ago

All checks with names started from clang-analyzer are implemented in Clang Static Analyzer, not Clang-tidy. Later just use them.