Skip to content

Commit

Permalink
Add ABSL_ATTRIBUTE_LIFETIME_BOUND attribute on generated string fie…
Browse files Browse the repository at this point in the history
…ld accessors.

This allows the compiler to statically detect use-after-free bugs.

This change touches a subset of field types. More changes to follow.

PiperOrigin-RevId: 559832961
  • Loading branch information
protobuf-github-bot authored and Copybara-Service committed Aug 24, 2023
1 parent aa0c2b1 commit 18c338a
Show file tree
Hide file tree
Showing 4 changed files with 304 additions and 212 deletions.
192 changes: 106 additions & 86 deletions src/google/protobuf/compiler/cpp/field_generators/cord_field.cc
Expand Up @@ -196,38 +196,48 @@ void CordFieldGenerator::GenerateAccessorDeclarations(

void CordFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const ::absl::Cord& $classname$::_internal_$name$() const {\n"
" return $field$;\n"
"}\n"
"inline const ::absl::Cord& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::_internal_set_$name$(const ::absl::Cord& "
"value) {\n"
" $set_hasbit$\n"
" $field$ = value;\n"
"}\n"
"inline void $classname$::set_$name$(const ::absl::Cord& value) {\n"
"$PrepareSplitMessageForWrite$"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(::absl::string_view value) {\n"
"$PrepareSplitMessageForWrite$"
" $set_hasbit$\n"
" $field$ = value;\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
"}\n"
"inline ::absl::Cord* $classname$::_internal_mutable_$name$() {\n"
" $set_hasbit$\n"
" return &$field$;\n"
"}\n");
auto v = printer->WithVars(variables_);
printer->Emit(R"cc(
inline const ::absl::Cord& $classname$::_internal_$name$() const {
return $field$;
}
)cc");
printer->Emit(R"cc(
inline const ::absl::Cord& $classname$::$name$() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_get$;
// @@protoc_insertion_point(field_get:$full_name$)
return _internal_$name$();
}
)cc");
printer->Emit(R"cc(
inline void $classname$::_internal_set_$name$(const ::absl::Cord& value) {
$set_hasbit$;
$field$ = value;
}
)cc");
printer->Emit(R"cc(
inline void $classname$::set_$name$(const ::absl::Cord& value) {
$PrepareSplitMessageForWrite$ _internal_set_$name$(value);
$annotate_set$;
// @@protoc_insertion_point(field_set:$full_name$)
}
)cc");
printer->Emit(R"cc(
inline void $classname$::set_$name$(::absl::string_view value) {
$PrepareSplitMessageForWrite$;
$set_hasbit$;
$field$ = value;
$annotate_set$;
// @@protoc_insertion_point(field_set_string_piece:$full_name$)
}
)cc");
printer->Emit(R"cc(
inline ::absl::Cord* $classname$::_internal_mutable_$name$() {
$set_hasbit$;
return &$field$;
}
)cc");
}

void CordFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
Expand Down Expand Up @@ -356,60 +366,70 @@ void CordOneofFieldGenerator::GenerateStaticMembers(

void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline const ::absl::Cord& $classname$::_internal_$name$() const {\n"
" if ($has_field$) {\n"
" return *$field$;\n"
" }\n"
" return $default_variable$;\n"
"}\n"
"inline const ::absl::Cord& $classname$::$name$() const {\n"
"$annotate_get$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::_internal_set_$name$(const ::absl::Cord& "
"value) {\n"
" if ($not_has_field$) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field$ = new ::absl::Cord;\n"
" if (GetArenaForAllocation() != nullptr) {\n"
" GetArenaForAllocation()->Own($field$);\n"
" }\n"
" }\n"
" *$field$ = value;\n"
"}\n"
"inline void $classname$::set_$name$(const ::absl::Cord& value) {\n"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(::absl::string_view value) {\n"
" if ($not_has_field$) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field$ = new ::absl::Cord;\n"
" if (GetArenaForAllocation() != nullptr) {\n"
" GetArenaForAllocation()->Own($field$);\n"
" }\n"
" }\n"
" *$field$ = value;\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
"}\n"
"inline ::absl::Cord* $classname$::_internal_mutable_$name$() {\n"
" if ($not_has_field$) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field$ = new ::absl::Cord;\n"
" if (GetArenaForAllocation() != nullptr) {\n"
" GetArenaForAllocation()->Own($field$);\n"
" }\n"
" }\n"
" return $field$;\n"
"}\n");
auto v = printer->WithVars(variables_);
printer->Emit(R"cc(
inline const ::absl::Cord& $classname$::_internal_$name$() const {
if ($has_field$) {
return *$field$;
}
return $default_variable$;
}
)cc");
printer->Emit(R"cc(
inline const ::absl::Cord& $classname$::$name$() const {
$annotate_get$;
// @@protoc_insertion_point(field_get:$full_name$)
return _internal_$name$();
}
)cc");
printer->Emit(R"cc(
inline void $classname$::_internal_set_$name$(const ::absl::Cord& value) {
if ($not_has_field$) {
clear_$oneof_name$();
set_has_$name$();
$field$ = new ::absl::Cord;
if (GetArenaForAllocation() != nullptr) {
GetArenaForAllocation()->Own($field$);
}
}
*$field$ = value;
}
)cc");
printer->Emit(R"cc(
inline void $classname$::set_$name$(const ::absl::Cord& value) {
_internal_set_$name$(value);
$annotate_set$;
// @@protoc_insertion_point(field_set:$full_name$)
}
)cc");
printer->Emit(R"cc(
inline void $classname$::set_$name$(::absl::string_view value) {
if ($not_has_field$) {
clear_$oneof_name$();
set_has_$name$();
$field$ = new ::absl::Cord;
if (GetArenaForAllocation() != nullptr) {
GetArenaForAllocation()->Own($field$);
}
}
*$field$ = value;
$annotate_set$;
// @@protoc_insertion_point(field_set_string_piece:$full_name$)
}
)cc");
printer->Emit(R"cc(
inline ::absl::Cord* $classname$::_internal_mutable_$name$() {
if ($not_has_field$) {
clear_$oneof_name$();
set_has_$name$();
$field$ = new ::absl::Cord;
if (GetArenaForAllocation() != nullptr) {
GetArenaForAllocation()->Own($field$);
}
}
return $field$;
}
)cc");
}

void CordOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
Expand Down
19 changes: 12 additions & 7 deletions src/google/protobuf/compiler/cpp/field_generators/string_field.cc
Expand Up @@ -452,7 +452,8 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
{"set_allocated_impl", [&] { SetAllocatedImpl(p); }},
},
R"cc(
inline const std::string& $Msg$::$name$() const {
inline const std::string& $Msg$::$name$() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_get$;
// @@protoc_insertion_point(field_get:$pkg.Msg.field$)
$if_IsDefault$;
Expand All @@ -468,7 +469,7 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
$annotate_set$;
// @@protoc_insertion_point(field_set:$pkg.Msg.field$)
}
inline std::string* $Msg$::mutable_$name$() {
inline std::string* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
$PrepareSplitMessageForWrite$;
std::string* _s = _internal_mutable_$name$();
$annotate_mutable$;
Expand Down Expand Up @@ -887,19 +888,22 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
: "");
}}},
R"cc(
inline std::string* $Msg$::add_$name$() {
inline std::string* $Msg$::add_$name$()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
$TsanDetectConcurrentMutation$;
std::string* _s = _internal_mutable_$name$()->Add();
$annotate_add_mutable$;
// @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$)
return _s;
}
inline const std::string& $Msg$::$name$(int index) const {
inline const std::string& $Msg$::$name$(int index) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_get$;
// @@protoc_insertion_point(field_get:$pkg.Msg.field$)
return _internal_$name$().$Get$(index$GetExtraArg$);
}
inline std::string* $Msg$::mutable_$name$(int index) {
inline std::string* $Msg$::mutable_$name$(int index)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_mutable$;
// @@protoc_insertion_point(field_mutable:$pkg.Msg.field$)
return _internal_mutable_$name$()->Mutable(index);
Expand Down Expand Up @@ -966,12 +970,13 @@ void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
// @@protoc_insertion_point(field_add_string_piece:$pkg.Msg.field$)
}
inline const ::$proto_ns$::RepeatedPtrField<std::string>&
$Msg$::$name$() const {
$Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_list$;
// @@protoc_insertion_point(field_list:$pkg.Msg.field$)
return _internal_$name$();
}
inline ::$proto_ns$::RepeatedPtrField<std::string>* $Msg$::mutable_$name$() {
inline ::$proto_ns$::RepeatedPtrField<std::string>*
$Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
$annotate_mutable_list$;
// @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
$TsanDetectConcurrentMutation$;
Expand Down

0 comments on commit 18c338a

Please sign in to comment.