Skip to content

Commit fffa3da

Browse files
Fixes #18726 by backslash escaping descriptor data containing # if the hashmark appears immediately before any of $, {, or @.
PiperOrigin-RevId: 730425377
1 parent bdb7433 commit fffa3da

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

src/google/protobuf/compiler/ruby/ruby_generator.cc

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,33 @@ std::string DumpImportList(const FileDescriptor* file) {
250250
return ret;
251251
}
252252

253+
namespace {
254+
255+
// Escape a string for use in a Ruby string literal. This is a superset of
256+
// absl::CHexEscape() that also includes handling of the following characters:
257+
// - # (hashmark)
258+
//
259+
// This is needed because Ruby double-quoted string literals interpolate the
260+
// contents of the string, and the hashmark character is used in the
261+
// interpolation syntax. Informed by MRI Ruby's implementation of String#dump.
262+
std::string RubyEscape(absl::string_view s) {
263+
std::string c_escaped = absl::CHexEscape(s);
264+
std::string result;
265+
result.reserve(c_escaped.length());
266+
for (size_t i = 0; i < c_escaped.length(); ++i) {
267+
if (c_escaped[i] == '#' &&
268+
(i + 1 < c_escaped.length() &&
269+
(c_escaped[i + 1] == '{' || c_escaped[i + 1] == '$' ||
270+
c_escaped[i + 1] == '@'))) {
271+
absl::StrAppend(&result, "\\");
272+
}
273+
absl::StrAppend(&result, c_escaped.substr(i, 1));
274+
}
275+
return result;
276+
}
277+
278+
} // namespace
279+
253280
void GenerateBinaryDescriptor(const FileDescriptor* file, io::Printer* printer,
254281
std::string* error) {
255282
printer->Print(R"(
@@ -259,9 +286,8 @@ pool = Google::Protobuf::DescriptorPool.generated_pool
259286
pool.add_serialized_file(descriptor_data)
260287
261288
)",
262-
"descriptor_data",
263-
absl::CHexEscape(SerializedDescriptor(file)), "imports",
264-
DumpImportList(file));
289+
"descriptor_data", RubyEscape(SerializedDescriptor(file)),
290+
"imports", DumpImportList(file));
265291
}
266292

267293
bool GenerateFile(const FileDescriptor* file, io::Printer* printer,

0 commit comments

Comments
 (0)