Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C-style string APIs for bytes types are prone to misuse (C++ generated code) #20552

Open
will-bartlett opened this issue Mar 3, 2025 · 0 comments
Labels
untriaged auto added to all issues by default when created.

Comments

@will-bartlett
Copy link

What language does this apply to?
C++ generated code.

Describe the problem you are trying to solve.
For a proto field definition:
string foo = 1;
Or:
bytes foo = 1;

Protobuf generates a C-style adapter:
void set_foo(const char* value);
that is atypical in modern C++ and prone to misuse. Internally, this method calls:
set_foo(value, std::strlen(value));
Which the caller could use directly, if desired.

Almost all C++ string types are buffer+length. Many of them support binary data. If components are needed, the appropriate method is
void set_foo(const char* value, int size);

Particularly when the proto declaration is bytes and not string (indicating binary data), it seems likely that std::strlen is not intended.

Describe the solution you'd like
Introduce an:
option features.(pb.cpp).generate_c_string_setter = false
Or features:
option features.(pb.cpp).generate_string_c_string_setter = false
option features.(pb.cpp).generate_bytes_c_string_setter = false
That controls whether such methods are generated.

Then, in a future edition, default it to false either for bytes or for both bytes and strings.

Protobuf should have a mode for modern C++ that disables all the C compatible stuff by default.

Describe alternatives you've considered
There seems to be a small tie-in to language edition. C string setters seem more reasonable in C89 / C++03 than in C23 / C++20. I considered suggesting that the default could vary by language-mode in some way - e.g. if generating C++20 headers, it could be excluded, if generating C++03 headers, it could be included - but that didn't seem clean.

Additional context
In my case, this signature caused an inadvertent truncation issue.
void func(protoType* obj, const char* binaryData, size_t length) {
ATL::CStringA str(binaryData, length);
obj->set_foo(str);
}

String classes (like ATL::CStringT) should probably avoid implicit conversions too, but it's the same issue both ways. ATL::CStringT is trying too hard to be C-compatible by including an implicit conversion, and protobuf is trying to be too hard to be C compatible by including C-string compatible method signatures.

@will-bartlett will-bartlett added the untriaged auto added to all issues by default when created. label Mar 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
untriaged auto added to all issues by default when created.
Projects
None yet
Development

No branches or pull requests

1 participant