protocolbuffers / protobuf

Protocol Buffers - Google's data interchange format
http://protobuf.dev
Other
65.78k stars 15.51k forks source link

regression: `valgrind: Unrecognised instruction at address` when using SerializeToString #3006

Closed timotheecour closed 7 years ago

timotheecour commented 7 years ago

valgrind ./my_program

==15137== Massif, a heap profiler
==15137== Copyright (C) 2003-2015, and GNU GPL'd, by Nicholas Nethercote
==15137== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==15137== Command: ./my_program
==15137== brk segment overflow in thread #1: can't grow to 0x4a28000
vex amd64->IR: unhandled instruction bytes: 0xF 0xC7 0xF0 0x89 0x6 0xF 0x42 0xC1
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=0F
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==15137== valgrind: Unrecognised instruction at address 0xa0d2b15.
==15137==    at 0xA0D2B15: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==15137==    by 0xA0D2CB1: std::random_device::_M_getval() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==15137==    by 0x85289B2: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::InnerMap::Seed() const (random.h:1612)
==15137==    by 0x8528BD8: google::protobuf::internal::MapField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value, (google::protobuf::internal::WireFormatLite::FieldType)9, (google::protobuf::internal::WireFormatLite::FieldType)11, 0>::MapField() (map.h:727)
==15137==    by 0x8522848: google::protobuf::Struct::Struct() (struct.pb.cc:213)
==15137==    by 0x85228ED: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct::InitDefaultsImpl() (struct.pb.cc:127)
==15137==    by 0x84903B4: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (callback.h:129)
==15137==    by 0x85202C4: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults() (once.h:128)
==15137==    by 0x8520308: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptorsImpl() (struct.pb.cc:147)
==15137==    by 0x84903B4: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (callback.h:129)
==15137==    by 0x8520394: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptors() (once.h:128)
==15137==    by 0x40104E9: call_init.part.0 (dl-init.c:72)
==15137== Your program just tried to execute an instruction that Valgrind
==15137== did not recognise.  There are two possible reasons for this.
==15137== 1. Your program has a bug and erroneously jumped to a non-code
==15137==    location.  If you are running Memcheck and you just saw a
==15137==    warning about a bad jump, it's probably your program's fault.
==15137== 2. The instruction is legitimate but Valgrind doesn't handle it,
==15137==    i.e. it's Valgrind's fault.  If you think this is the case or
==15137==    you are not sure, please let us know and we'll try to fix it.
==15137== Either way, Valgrind will now raise a SIGILL signal which will
==15137== probably kill your program.
==15137==
==15137== Process terminating with default action of signal 4 (SIGILL)
==15137==  Illegal opcode at address 0xA0D2B15
==15137==    at 0xA0D2B15: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==15137==    by 0xA0D2CB1: std::random_device::_M_getval() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==15137==    by 0x85289B2: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::InnerMap::Seed() const (random.h:1612)
==15137==    by 0x8528BD8: google::protobuf::internal::MapField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value, (google::protobuf::internal::WireFormatLite::FieldType)9, (google::protobuf::internal::WireFormatLite::FieldType)11, 0>::MapField() (map.h:727)
==15137==    by 0x8522848: google::protobuf::Struct::Struct() (struct.pb.cc:213)
==15137==    by 0x85228ED: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct::InitDefaultsImpl() (struct.pb.cc:127)
==15137==    by 0x84903B4: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (callback.h:129)
==15137==    by 0x85202C4: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults() (once.h:128)
==15137==    by 0x8520308: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptorsImpl() (struct.pb.cc:147)
==15137==    by 0x84903B4: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (callback.h:129)
==15137==    by 0x8520394: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptors() (once.h:128)
==15137==    by 0x40104E9: call_init.part.0 (dl-init.c:72)

to reproduce:

main.cpp:

#include <string>
#include <google/protobuf/message.h>

void test_pb(google::protobuf::Message* a){
  std::string msg;
  auto temp=a->SerializeToString(&msg);
}

int main(int argc, char** argv) {
  return 0;
}

Makefile:

proto_D=/path/to/protolib
other=${proto_D}/libprotobuf.so

all:
    clang++ -o /tmp/main main.cpp -std=c++14 ${other}
    LD_LIBRARY_PATH=${proto_D} valgrind /tmp/main

NOTE: everything works fine with libprotobuf.so.9.0.1 (eg: proto_D=/usr/lib/x86_64-linux-gnu/) but the valgrind failure happens with libprotoc.so.12.0.0 (eg from linuxbrew) also fails with https://github.com/google/protobuf GIT_TAG 15b60bccf8992f7ff0897705e43aa8ab8889cd02

clang++ -o /tmp/test_temp test_temp.cpp -std=c++14 path_to_proto/libprotobuf.so
LD_LIBRARY_PATH=path_to_proto valgrind /tmp/test_temp
==14315== Memcheck, a memory error detector
==14315== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14315== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14315== Command: /tmp/test_temp
==14315==
vex amd64->IR: unhandled instruction bytes: 0xF 0xC7 0xF0 0x89 0x44 0x24 0xC 0xF
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=0F
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==14315== valgrind: Unrecognised instruction at address 0x52cb5cf.
==14315==    at 0x52CB5CF: std::(anonymous namespace)::__x86_rdrand() (random.cc:69)
==14315==    by 0x52CB6C5: std::random_device::_M_getval() (random.cc:130)
==14315==    by 0x4F733EA: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::InnerMap::Seed() const (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F73681: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::Init() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F737DF: google::protobuf::internal::MapField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value, (google::protobuf::internal::WireFormatLite::FieldType)9, (google::protobuf::internal::WireFormatLite::FieldType)11, 0>::MapField() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6FB98: google::protobuf::Struct::Struct() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6FC71: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct::InitDefaultsImpl() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F179C9: google::protobuf::internal::FunctionClosure0::Run() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F18137: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F17A1C: google::protobuf::GoogleOnceInit(long*, void (*)()) (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6E8A2: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptorsImpl() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F179C9: google::protobuf::internal::FunctionClosure0::Run() (in path_to_proto/libprotobuf.so.12.0.0)
==14315== Your program just tried to execute an instruction that Valgrind
==14315== did not recognise.  There are two possible reasons for this.
==14315== 1. Your program has a bug and erroneously jumped to a non-code
==14315==    location.  If you are running Memcheck and you just saw a
==14315==    warning about a bad jump, it's probably your program's fault.
==14315== 2. The instruction is legitimate but Valgrind doesn't handle it,
==14315==    i.e. it's Valgrind's fault.  If you think this is the case or
==14315==    you are not sure, please let us know and we'll try to fix it.
==14315== Either way, Valgrind will now raise a SIGILL signal which will
==14315== probably kill your program.
==14315==
==14315== Process terminating with default action of signal 4 (SIGILL)
==14315==  Illegal opcode at address 0x52CB5CF
==14315==    at 0x52CB5CF: std::(anonymous namespace)::__x86_rdrand() (random.cc:69)
==14315==    by 0x52CB6C5: std::random_device::_M_getval() (random.cc:130)
==14315==    by 0x4F733EA: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::InnerMap::Seed() const (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F73681: google::protobuf::Map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value>::Init() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F737DF: google::protobuf::internal::MapField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, google::protobuf::Value, (google::protobuf::internal::WireFormatLite::FieldType)9, (google::protobuf::internal::WireFormatLite::FieldType)11, 0>::MapField() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6FB98: google::protobuf::Struct::Struct() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6FC71: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct::InitDefaultsImpl() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F179C9: google::protobuf::internal::FunctionClosure0::Run() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F18137: google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*) (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F17A1C: google::protobuf::GoogleOnceInit(long*, void (*)()) (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F6E8A2: google::protobuf::protobuf_google_2fprotobuf_2fstruct_2eproto::AddDescriptorsImpl() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==    by 0x4F179C9: google::protobuf::internal::FunctionClosure0::Run() (in path_to_proto/libprotobuf.so.12.0.0)
==14315==
==14315== HEAP SUMMARY:
==14315==     in use at exit: 79,051 bytes in 111 blocks
==14315==   total heap usage: 1,197 allocs, 1,086 frees, 135,665 bytes allocated
==14315==
==14315== LEAK SUMMARY:
==14315==    definitely lost: 0 bytes in 0 blocks
==14315==    indirectly lost: 0 bytes in 0 blocks
==14315==      possibly lost: 0 bytes in 0 blocks
==14315==    still reachable: 79,051 bytes in 111 blocks
==14315==         suppressed: 0 bytes in 0 blocks
==14315== Rerun with --leak-check=full to see details of leaked memory
==14315==
==14315== For counts of detected and suppressed errors, rerun with: -v
==14315== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Illegal instruction

NOTE: CMakeLists.txt used for installing protobufs; but shouldn't matter since i can also reproduce bug from linuxbrew

cmake_minimum_required(VERSION 2.8.3)
project(protobuf)
find_package(catkin REQUIRED)
include(ExternalProject)

ExternalProject_Add(${PROJECT_NAME}-upstream
  PREFIX upstream
  GIT_REPOSITORY https://github.com/google/protobuf.git
  GIT_TAG 15b60bccf8992f7ff0897705e43aa8ab8889cd02

  BUILD_IN_SOURCE 1

  UPDATE_COMMAND ""
  CONFIGURE_COMMAND ./autogen.sh
            COMMAND ./configure --prefix ${CATKIN_DEVEL_PREFIX} --disable-static
  BUILD_COMMAND /bin/bash -c "make -j $(/usr/bin/nproc)"
)

file(MAKE_DIRECTORY ${CATKIN_DEVEL_PREFIX}/include)

catkin_package(
  LIBRARIES protobuf
  INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/include
  CFG_EXTRAS ${PROJECT_NAME}_extras.cmake
)
timotheecour commented 7 years ago

EDIT: also failed with:

#include <google/protobuf/message.h>

int main(int argc, char** argv) {
  GOOGLE_PROTOBUF_VERIFY_VERSION;
  return 0;
}

and adding proper -I flag during compilation

timotheecour commented 7 years ago

EDIT: fixed by upgrading from valgrind-3.11.0 to valgrind-3.12.0 (eg via linuxbrew)