protobuf icon indicating copy to clipboard operation
protobuf copied to clipboard

SegFault accessing `Any` in `Map`

Open Chekov2k opened this issue 1 year ago • 4 comments

Im using protobuf 29.1 with llvm 19.1.5 on Mac OS X 15.1.1 (24B91) to generate C++ bindings:

brew info protobuf
==> protobuf: stable 29.1 (bottled)
brew info llvm
==> llvm: stable 19.1.5 (bottled), HEAD [keg-only]

What did you do?

Since the switch to 29.X my code segfaults with EXC_BAD_ACCESS.

I have narrowed it down to an access to an Any in a Map that was filled previously. The proto spec is

syntax = "proto3";
package test;

import "google/protobuf/any.proto";

message Message{
    string content = 1;
}

message Map {
    map<string, google.protobuf.Any> any = 1;
}

and the C++ code is generated like this: protoc --cpp_out . test.proto

The C++ minimal reproducer is:

#include <iostream>

#include "test.pb.h"

using namespace test;

int main() {
  Map map;
  Message message;
  message.set_content("test");
  if ((*map.mutable_any())["test"].PackFrom(message))
    std::cout << map.DebugString() << std::endl;
}

compiled using this command clang++ -fclang-abi-compat=17 $(pkg-config --cflags --libs protobuf) test.pb.cc main.cpp -o test

What did you expect to see

The debug string is printed correctly.

What did you see instead?

A segfault occurs:

lldb -- ./test
(lldb) target create "./test"
Current executable set to '/Users/balzer/Downloads/test' (arm64).
(lldb) run
Process 34287 launched: '/Users/balzer/Downloads/test' (arm64)
1
Process 34287 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
error: memory read failed for 0x0
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x000000010044b398 libprotobuf.29.1.0.dylib`google::protobuf::internal::MapFieldPrinterHelper::SortMap(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, std::__1::vector<google::protobuf::Message const*, std::__1::allocator<google::protobuf::Message const*>>*) + 520
    frame #2: 0x000000010044a7fc libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintField(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, google::protobuf::TextFormat::BaseTextGenerator*) const + 212
    frame #3: 0x000000010044a684 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintMessage(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 612
    frame #4: 0x0000000100449948 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 292
    frame #5: 0x0000000100449694 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::io::ZeroCopyOutputStream*, google::protobuf::internal::FieldReporterLevel) const + 72
    frame #6: 0x00000001004467f8 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintToString(google::protobuf::Message const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*) const + 84
    frame #7: 0x00000001004468b0 libprotobuf.29.1.0.dylib`google::protobuf::Message::DebugString() const + 152
    frame #8: 0x00000001000148f4 test`main + 244
    frame #9: 0x0000000183670274 dyld`start + 2840

Anything else we should know about your project / environment

It is not just accessing the debug string, any access to the stored Any results in a segfault. Any idea what is going on?

I also tested different ways of inserting into the Map and they all fail:

#include <iostream>
#include <string>

#include <google/protobuf/any.pb.h>

#include "test.pb.h"

using namespace test;

int main() {
  Map map;
  Message message;
  message.set_content("test");

  google::protobuf::Any any;
  if(any.PackFrom(message)) {
    map.mutable_any()->insert(std::make_pair<std::string, google::protobuf::Any>("test", std::move(any)));
    std::cout << map.DebugString() << std::endl;
  }
}

Chekov2k avatar Dec 09 '24 09:12 Chekov2k

Is this specific to just Any? Would it happen with user-defined messages? What about other built-in messages, like some of the messages from descriptor.proto? Is this only with string keys? or also with integral keys?

sbenzaquen avatar Dec 09 '24 17:12 sbenzaquen

Is this specific to just Any? Would it happen with user-defined messages? What about other built-in messages, like some of the messages from descriptor.proto? Is this only with string keys? or also with integral keys?

I can confirm the segfaults happens for custom messages as well, i.e:

syntax = "proto3";
package test;

message Message{
    string content = 1;
}

message Map {
    map<string, Message> custom = 1;
  }

and

#include <iostream>
#include <string>

#include "test.pb.h"

using namespace test;

int main() {
  Map map;
  Message message;
  message.set_content("test");
  (*map.mutable_custom())["test"] = message;
  std::cout << map.DebugString() << std::endl;
}

with segfault

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
error: memory read failed for 0x0
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x000000010044b398 libprotobuf.29.1.0.dylib`google::protobuf::internal::MapFieldPrinterHelper::SortMap(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, std::__1::vector<google::protobuf::Message const*, std::__1::allocator<google::protobuf::Message const*>>*) + 520
    frame #2: 0x000000010044a7fc libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintField(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, google::protobuf::TextFormat::BaseTextGenerator*) const + 212
    frame #3: 0x000000010044a684 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintMessage(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 612
    frame #4: 0x0000000100449948 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 292
    frame #5: 0x0000000100449694 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::io::ZeroCopyOutputStream*, google::protobuf::internal::FieldReporterLevel) const + 72
    frame #6: 0x00000001004467f8 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintToString(google::protobuf::Message const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*) const + 84
    frame #7: 0x00000001004468b0 libprotobuf.29.1.0.dylib`google::protobuf::Message::DebugString() const + 152
    frame #8: 0x0000000100014c7c test`main + 192
    frame #9: 0x0000000183670274 dyld`start + 2840

Also using an integral key results in a segfault:

syntax = "proto3";
package test;

message Message{
    string content = 1;
}

message Map {
    map<int32, Message> custom = 1;
  }

code:

#include <iostream>
#include <string>

#include "test.pb.h"

using namespace test;

int main() {
  Map map;
  Message message;
  message.set_content("test");
  (*map.mutable_custom())[1] = message;
  std::cout << map.DebugString() << std::endl;
}

Segfault:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
error: memory read failed for 0x0
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x0000000100443398 libprotobuf.29.1.0.dylib`google::protobuf::internal::MapFieldPrinterHelper::SortMap(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, std::__1::vector<google::protobuf::Message const*, std::__1::allocator<google::protobuf::Message const*>>*) + 520
    frame #2: 0x00000001004427fc libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintField(google::protobuf::Message const&, google::protobuf::Reflection const*, google::protobuf::FieldDescriptor const*, google::protobuf::TextFormat::BaseTextGenerator*) const + 212
    frame #3: 0x0000000100442684 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintMessage(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 612
    frame #4: 0x0000000100441948 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::TextFormat::BaseTextGenerator*) const + 292
    frame #5: 0x0000000100441694 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::io::ZeroCopyOutputStream*, google::protobuf::internal::FieldReporterLevel) const + 72
    frame #6: 0x000000010043e7f8 libprotobuf.29.1.0.dylib`google::protobuf::TextFormat::Printer::PrintToString(google::protobuf::Message const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*) const + 84
    frame #7: 0x000000010043e8b0 libprotobuf.29.1.0.dylib`google::protobuf::Message::DebugString() const + 152
    frame #8: 0x00000001000152a8 test`main + 196
    frame #9: 0x0000000183670274 dyld`start + 2840

Chekov2k avatar Dec 10 '24 06:12 Chekov2k

Any news on this one?

Chekov2k avatar Jan 06 '25 08:01 Chekov2k

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. This issue will be closed and archived after 14 additional days without activity.

github-actions[bot] avatar Apr 06 '25 10:04 github-actions[bot]

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 reopen it.

This issue was closed and archived because there has been no new activity in the 14 days since the inactive label was added.

github-actions[bot] avatar Apr 21 '25 10:04 github-actions[bot]