protocolbuffers / protobuf

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

Stack smashing before `main()` caused by adding `import` to quick start's greeter proto file #12732

Open keith-bennett-airmap opened 1 year ago

keith-bennett-airmap commented 1 year ago

Note that I originally thought this is a bug in the gRPC generator, so I filed an issue here. However, I have since realized that this is an issue in protobuf: I can reproduce the issue without grpc.

What version of protobuf and what language are you using? Version: v21.12 Version: v20.2 Version: v19.5 Version: v18.3 Version: v16.2 Version: v3.10.1 Version: v3.6.1.3

Language: C++

What operating system (Linux, Windows, ...) and version? Ubuntu 20.04 LTS

What runtime / compiler are you using (e.g., python version or gcc version) gcc --version ->

gcc (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

What did you do?

  1. Use the Greeter service quickstart example from grpc.io found here.
    1. Copy-pasted the first proto file text found in the quick start website into ./src/proto/greeter.proto
    2. I did not copy the .proto file from the grpc repository
  2. Add import "google/api/field_behavior.proto"; to import a .proto file from googleapis repository here.
  3. Compile the .proto files to generate C++ header and source files into a static library
  4. Instantiate HelloRequest and HelloReply in an executable which links against the static library
  5. Run the built executable

This is verified in a repository I created with a demonstration here.

You can run ./build.sh. It will:

  1. :warning: Prune Docker then remove existing protobuf-toolchain and protobuf-stacksmash images to keep Docker from using tons of resources while iterating changes to the source tree
  2. :information_source: Find or create a few toolchain images
    1. Find, or create and tag, ubuntu-2004-toolchain image which includes only the Ubuntu packages required to compile
      1. this takes a couple minutes
      2. gcc-11 is installed from ubuntu-toolchain PPA
    2. Find, or create and tag, cmake-toolchain image which builds and installs cmake from source
    3. Find, or create and tag, protobuf-toolchain image which builds and installs protobuf from source
      1. NOTE: this image enables Address Sanitizer via environment variables to enforce ASAN throughout the demonstration.
      2. Here is protobuf version. Note that I use version v21.12 due to a separate issue found while constructing this demonstration.
      3. Here is grpc version
  3. :information_source: Create and tag a new protobuf-stacksmash image which compiles a demonstration
  4. :exclamation: Runs the newly-created protobuf-stacksmash image to demonstrate whether the resulting executable is viable

What did you expect to see :heavy_check_mark: Per initial commit here: ./build.sh ->

Successfully built 55df7a9eb834
Successfully tagged grpc-stacksmash:latest
greeter service created -- no stacksmash

What did you see instead? :exclamation: :stop_sign: ./build.sh ->

Successfully tagged protobuf-stacksmash:latest
*** stack smashing detected ***: terminated
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x7f5ca1291941 bp 0x7ffcad720d20 sp 0x7ffcad720ac0 T0)
==1==The signal is caused by a READ memory access.
==1==Hint: this fault was caused by a dereference of a high value address (see register values below).  Dissassemble the provided pc to learn which register was used.
    #0 0x7f5ca1291941 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22941)
    #1 0x7f5ca12fc26d  (/lib/x86_64-linux-gnu/libc.so.6+0x8d26d)
    #2 0x7f5ca139eab9 in __fortify_fail (/lib/x86_64-linux-gnu/libc.so.6+0x12fab9)
    #3 0x7f5ca139ea85 in __stack_chk_fail (/lib/x86_64-linux-gnu/libc.so.6+0x12fa85)
    #4 0x7f5ca1958f90 in google::protobuf::EncodedDescriptorDatabase::Add(void const*, int) google/protobuf/descriptor_database.cc:322
    #5 0x7f5ca1925663 in google::protobuf::DescriptorPool::InternalAddGeneratedFile(void const*, int) google/protobuf/descriptor.cc:1358
    #6 0x7f5ca191c49d in protobuf_google_2fprotobuf_2fany_2eproto::AddDescriptorsImpl() google/protobuf/any.pb.cc:97
    #7 0x7f5ca17f84de in __pthread_once_slow (/lib/x86_64-linux-gnu/libpthread.so.0+0x114de)
    #8 0x7f5ca191c65e in __gthread_once /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:700
    #9 0x7f5ca191c65e in void std::call_once<void (&)()>(std::once_flag&, void (&)()) /usr/include/c++/11/mutex:783
    #10 0x7f5ca191c65e in void google::protobuf::internal::call_once<std::once_flag&, void (&)()>(std::once_flag&, void (&)()) google/protobuf/stubs/once.h:91
    #11 0x7f5ca191c65e in protobuf_google_2fprotobuf_2fany_2eproto::AddDescriptors() google/protobuf/any.pb.cc:105
    #12 0x7f5ca24b3b99  (/lib64/ld-linux-x86-64.so.2+0x11b99)
    #13 0x7f5ca24b3ca0  (/lib64/ld-linux-x86-64.so.2+0x11ca0)
    #14 0x7f5ca24a3139  (/lib64/ld-linux-x86-64.so.2+0x1139)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x22941) in abort
==1==ABORTING

Anything else we should know about your project / environment

./build.sh is the driver for the demo.

./docker contains Dockerfiles and scripts to set up the build toolchain. ./docker/ubuntu-2004-toolchain.Dockerfile installs GCC ./docker/cmake-toolchain.Dockerfile inherits FROM ubuntu-2004-toolchain and builds & installs cmake ./docker/protobuf-toolchain.Dockerfile inherits FROM cmake-toolchain and builds & installs protobufs (especially protoc). The version of protobuf can be configured as an argument. ./Dockerfile inherits FROM protobuf-toolchain and builds the project with cmake.

./src contains the stack smashing demo ./src/proto/external contains a static library whose only purpose is to compile external proto files -- eg proto files that were nominally downloaded from elsewhere (eg, here. ./src/proto contains a static library whose only purpose is to compile proto files into a static library. It contains the greeter service proto. It then links to and imports the external protos. ./src/greeter-service contains an executable. Its only purpose is to link against the static proto library and instantiate the objects that were generated.

The ./Dockerfile then sets greeter-service as its entrypoint so that docker run will run the demo.

This problem is a Minimal Compilable Reproducible Example that has been trimmed down from a larger codebase. The larger codebase includes several golang projects which are currently using the .proto files being imported. This issue blocks me from building a C++ project to communicate with several golang projects that are already importing this file.

keith-bennett-airmap commented 1 year ago

Note: other (golang) projects in the larger product use protobuf v22.2. I couldn't use that because of build issues.

I've tracked those build issues down to a problem with Address Sanitizer which I normally have turned on for all debug builds. I have created a separate issue for that problem.

However, other than the build issue with Address Sanitizer, v22.4 does not appear to have this stack smashing issue.

github-actions[bot] commented 10 months ago

We triage inactive PRs and issues in order to make it easier to find active work. If this issue should remain active or becomes active again, please add a comment.

This issue is labeled inactive because the last activity was over 90 days ago.

keith-bennett-airmap commented 10 months ago

This stack smashing issue has cropped up, in a private repository, once or twice since last posting here. The most recent workaround seems to be to use the minimal grpc lib instead of the full grpc lib, but I'm not convinced that truly solves the problem since it appears to be related to protobuf itself.