protocolbuffers / protocolbuffers/protobuf

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

Open
#12,732 3 comments 0 reactions 1 assignee View on GitHub

@sbenzaquen is already working on this.

Since May 15, 2023.

c++ help wanted
Dominant language
C++
Stars
72k
Forks
16.3k
Avg merge
1d 17h
Merged PRs (30d)
140

Description

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. ⚠️ 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. ℹ️ 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. ℹ️ Create and tag a new protobuf-stacksmash image which compiles a demonstration
  4. Runs the newly-created protobuf-stacksmash image to demonstrate whether the resulting executable is viable

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

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

What did you see instead?
❗ 🛑 ./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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.