Uploaded image for project: 'Qpid Proton'
  1. Qpid Proton
  2. PROTON-1556

[proton-cpp] ssl_client_options is not self-assignable

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Critical
    • Resolution: Fixed
    • proton-c-0.18.0
    • proton-c-0.19.0
    • cpp-binding
    • None

    Description

      ssl_client_options probably cannot be self-assigned. See the attached report from clang-analyzer, which looks very plausible.

      The problem is that assuming x == *this, the assignment operator will decref and then incref the same value. Assuming the reference count was 1 to start with, there will be use-after-free.

      This probably does not matter that much in real-world code, but I found some quotations that making self assignment work is really important in C++...

      58	ssl_domain& internal::ssl_domain::operator=(const ssl_domain&x) {
      59	    if (impl_) impl_->decref();
      60	    impl_ = x.impl_;
      61	    server_type_ = x.server_type_;
      62	    if (impl_) impl_->incref();
      63	    return *this;
      64	}
      

      I believe the static analyzer is correct, because when I do not make any changes to the examples/cpp/ssl example, Valgrind does not report errors concerning the class, but if I add a ssl_cli = ssl_cli;, then I get

      $ valgrind ./ssl -c /home/jdanek/Work/repos/qpid-proton/examples/cpp/ssl_certs/
      ==4950== Memcheck, a memory error detector
      ==4950== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
      ==4950== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
      ==4950== Command: ./ssl -c /home/jdanek/Work/repos/qpid-proton/examples/cpp/ssl_certs/
      ==4950== 
      ==4950== Invalid read of size 4
      ==4950==    at 0x4E715CC: incref (ssl_domain.cpp:37)
      ==4950==    by 0x4E715CC: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:62)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Address 0x766a3c0 is 0 bytes inside a block of size 16 free'd
      ==4950==    at 0x4C2D2EB: operator delete(void*) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E715FA: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E715FA: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:59)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Block was alloc'd at
      ==4950==    at 0x4C2C22F: operator new(unsigned long) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E7166C: proton::internal::ssl_domain::pn_domain() (ssl_domain.cpp:72)
      ==4950==    by 0x4E7195C: proton::ssl_client_options::ssl_client_options(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, proton::ssl::verify_mode) (ssl_domain.cpp:120)
      ==4950==    by 0x4032B9: main (ssl.cpp:175)
      ==4950== 
      ==4950== Invalid read of size 4
      ==4950==    at 0x4E71619: decref (ssl_domain.cpp:39)
      ==4950==    by 0x4E71619: proton::internal::ssl_domain::~ssl_domain() (ssl_domain.cpp:66)
      ==4950==    by 0x4032F8: ~ssl_client_options (ssl.hpp:172)
      ==4950==    by 0x4032F8: main (ssl.cpp:175)
      ==4950==  Address 0x766a3c0 is 0 bytes inside a block of size 16 free'd
      ==4950==    at 0x4C2D2EB: operator delete(void*) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E715FA: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E715FA: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:59)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Block was alloc'd at
      ==4950==    at 0x4C2C22F: operator new(unsigned long) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E7166C: proton::internal::ssl_domain::pn_domain() (ssl_domain.cpp:72)
      ==4950==    by 0x4E7195C: proton::ssl_client_options::ssl_client_options(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, proton::ssl::verify_mode) (ssl_domain.cpp:120)
      ==4950==    by 0x4032B9: main (ssl.cpp:175)
      ==4950== 
      ==4950== Invalid read of size 8
      ==4950==    at 0x4E71620: ~ssl_domain_impl (ssl_domain.cpp:36)
      ==4950==    by 0x4E71620: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E71620: proton::internal::ssl_domain::~ssl_domain() (ssl_domain.cpp:66)
      ==4950==    by 0x4032F8: ~ssl_client_options (ssl.hpp:172)
      ==4950==    by 0x4032F8: main (ssl.cpp:175)
      ==4950==  Address 0x766a3c8 is 8 bytes inside a block of size 16 free'd
      ==4950==    at 0x4C2D2EB: operator delete(void*) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E715FA: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E715FA: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:59)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Block was alloc'd at
      ==4950==    at 0x4C2C22F: operator new(unsigned long) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E7166C: proton::internal::ssl_domain::pn_domain() (ssl_domain.cpp:72)
      ==4950==    by 0x4E7195C: proton::ssl_client_options::ssl_client_options(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, proton::ssl::verify_mode) (ssl_domain.cpp:120)
      ==4950==    by 0x4032B9: main (ssl.cpp:175)
      ==4950== 
      ==4950== Invalid read of size 4
      ==4950==    at 0x52B8840: pn_ssl_domain_free (openssl.c:559)
      ==4950==    by 0x4E71628: ~ssl_domain_impl (ssl_domain.cpp:36)
      ==4950==    by 0x4E71628: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E71628: proton::internal::ssl_domain::~ssl_domain() (ssl_domain.cpp:66)
      ==4950==    by 0x4032F8: ~ssl_client_options (ssl.hpp:172)
      ==4950==    by 0x4032F8: main (ssl.cpp:175)
      ==4950==  Address 0x76c1c08 is 24 bytes inside a block of size 40 free'd
      ==4950==    at 0x4C2CDEB: free (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E715ED: ~ssl_domain_impl (ssl_domain.cpp:36)
      ==4950==    by 0x4E715ED: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E715ED: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:59)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Block was alloc'd at
      ==4950==    at 0x4C2DBD5: calloc (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x52B8C26: pn_ssl_domain (openssl.c:490)
      ==4950==    by 0x4E71BB9: proton::ssl_domain_impl::ssl_domain_impl(bool) (ssl_domain.cpp:33)
      ==4950==    by 0x4E7167B: proton::internal::ssl_domain::pn_domain() (ssl_domain.cpp:72)
      ==4950==    by 0x4E7195C: proton::ssl_client_options::ssl_client_options(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, proton::ssl::verify_mode) (ssl_domain.cpp:120)
      ==4950==    by 0x4032B9: main (ssl.cpp:175)
      ==4950== 
      ==4950== Invalid free() / delete / delete[] / realloc()
      ==4950==    at 0x4C2D2EB: operator delete(void*) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4032F8: ~ssl_client_options (ssl.hpp:172)
      ==4950==    by 0x4032F8: main (ssl.cpp:175)
      ==4950==  Address 0x766a3c0 is 0 bytes inside a block of size 16 free'd
      ==4950==    at 0x4C2D2EB: operator delete(void*) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E715FA: decref (ssl_domain.cpp:40)
      ==4950==    by 0x4E715FA: proton::internal::ssl_domain::operator=(proton::internal::ssl_domain const&) (ssl_domain.cpp:59)
      ==4950==    by 0x4032F0: operator= (ssl.hpp:172)
      ==4950==    by 0x4032F0: main (ssl.cpp:176)
      ==4950==  Block was alloc'd at
      ==4950==    at 0x4C2C22F: operator new(unsigned long) (in /nix/store/gv9x2j31hvn0wf37h4jmb9xz6vgc3vvv-valgrind-3.12.0/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==4950==    by 0x4E7166C: proton::internal::ssl_domain::pn_domain() (ssl_domain.cpp:72)
      ==4950==    by 0x4E7195C: proton::ssl_client_options::ssl_client_options(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, proton::ssl::verify_mode) (ssl_domain.cpp:120)
      ==4950==    by 0x4032B9: main (ssl.cpp:175)
      ==4950== 
      ==4950== 
      ==4950== HEAP SUMMARY:
      ==4950==     in use at exit: 98,536 bytes in 3,275 blocks
      ==4950==   total heap usage: 3,651 allocs, 377 frees, 237,715 bytes allocated
      ==4950== 
      ==4950== LEAK SUMMARY:
      ==4950==    definitely lost: 0 bytes in 0 blocks
      ==4950==    indirectly lost: 0 bytes in 0 blocks
      ==4950==      possibly lost: 0 bytes in 0 blocks
      ==4950==    still reachable: 98,536 bytes in 3,275 blocks
      ==4950==         suppressed: 0 bytes in 0 blocks
      ==4950== Rerun with --leak-check=full to see details of leaked memory
      ==4950== 
      ==4950== For counts of detected and suppressed errors, rerun with: -v
      ==4950== ERROR SUMMARY: 8 errors from 5 contexts (suppressed: 0 from 0)
      

      Hat tip to rkubis for help with C++.

      Attachments

        1. report-7646dc.html
          27 kB
          Jiri Daněk

        Activity

          People

            cliffjansen Clifford Jansen
            jdanek Jiri Daněk
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: