https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68281

            Bug ID: 68281
           Summary: '&&' is checked in reverse and reads an uninitialized
                    value
           Product: gcc
           Version: 5.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jistone at redhat dot com
                CC: fche at redhat dot com, law at redhat dot com, mark at gcc 
dot gnu.org
  Target Milestone: ---

Created attachment 36683
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36683&action=edit
tapsets.cxx and -save-temps

I have a C++ class with these members:

  bool has_callees_num;
  long callees_num_val;

In the constructor, they are set and used like this (with line numbers):

1001  has_callees_num = get_number_param(params, TOK_CALLEES, callees_num_val);
1002  if (has_callees_num && callees_num_val < 1)
1003    throw SEMANTIC_ERROR(/*...*/);

The get_number_param() takes val by reference and returns true if it sets val,
otherwise returns false.  When false, val is still uninitialized.

Valgrind complains on the "if" line 1002:

==29038== Conditional jump or move depends on uninitialised value(s)
==29038==    at 0x51E884: dwarf_query::dwarf_query(probe*, probe_point*,
dwflpp&, std::map<interned_string, literal*, std::less<interned_string>,
std::allocator<std::pair<interned_string const, literal*> > > const&,
std::vector<derived_probe*, std::allocator<derived_probe*> >&, interned_string,
interned_string) (tapsets.cxx:1002)

In disassembly, it appears that the code is in fact checking the RHS of the
'&&' first, then the LHS.

  51e86a:       e8 61 11 f5 ff          callq  46f9d0
<_ZN21derived_probe_builder9get_paramERKSt3mapI15interned_stringP7literalSt4lessIS1_ESaISt4pairIKS1_S3_EEES1_Rl>
  51e86f:       48 8b 54 24 20          mov    0x20(%rsp),%rdx
  51e874:       88 83 58 02 00 00       mov    %al,0x258(%rbx)
  51e87a:       48 85 d2                test   %rdx,%rdx
  51e87d:       48 89 93 60 02 00 00    mov    %rdx,0x260(%rbx)
  51e884:       0f 8f 64 fc ff ff       jg     51e4ee
<_ZN11dwarf_queryC1EP5probeP11probe_pointR6dwflppRKSt3mapI15interned_stringP7literalSt4lessIS7_ESaISt4pairIKS7_S9_EEERSt6vectorIP13derived_probeSaISL_EES7_S7_+0x74e>
  51e88a:       84 c0                   test   %al,%al
  51e88c:       0f 84 5c fc ff ff       je     51e4ee
<_ZN11dwarf_queryC1EP5probeP11probe_pointR6dwflppRKSt3mapI15interned_stringP7literalSt4lessIS7_ESaISt4pairIKS7_S9_EEERSt6vectorIP13derived_probeSaISL_EES7_S7_+0x74e>
  51e892:       bf 60 00 00 00          mov    $0x60,%edi
  51e897:       e8 d4 d9 ee ff          callq  40c270
<__cxa_allocate_exception@plt>

- "test %rdx,%rdx ; jg" is for false "callees_num_val < 1", the RHS of &&
- "test %al,%al; je" is for false "has_callees_num", the LHS of &&

I'm using Fedora 23, gcc version 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)
(Jeff Law suggested the bug would be better here than in RH bugzilla.)

Attachment contains:
- make-stap-tapsets : g++ command line from make
- tapsets.cxx : original source, see line 1002
- tapsets.ii : preprocessed source, same code is at line 135328
- tapsets_ZN11dwarf_queryC.s : assembly excerpt, see from line 1626 near
.LBE228880
(full tapsets.s was too big to attach, even compressed)

Reply via email to