diff --git a/content/editions/features.md b/content/editions/features.md
index 424da25c7..cec962d81 100644
--- a/content/editions/features.md
+++ b/content/editions/features.md
@@ -472,7 +472,7 @@ message Msg {
This feature determines how generated code should treat string fields. This
replaces the `ctype` option from proto2 and proto3, and offers a new
-`string_view` feature. In Edition 2023, either `ctype` or `string_view` may be
+`string_view` feature. In Edition 2023, either `ctype` or `string_type` may be
specified on a field, but not both.
**Values available:**
diff --git a/content/includes/version-tables.css b/content/includes/version-tables.css
index 1e84fe95c..c0fb516d3 100644
--- a/content/includes/version-tables.css
+++ b/content/includes/version-tables.css
@@ -95,36 +95,36 @@ table.version-chart td.active {
/* latest release column */
/*
* How to advance the selection of the latest release:
- * Replace class 'y24q3' in the following selectors with 'y24q4' (the class
+ * Replace class 'y24q4' in the following selectors with 'y25q1' (the class
* referring to the quarter of the next release). Please also update this
* instruction as a courtesy to the next maintainer.
*/
/* visually replace 'yyQq' heading with string 'Latest' */
-table.version-chart th.y24q3 span {
+table.version-chart th.y24q4 span {
display: none;
}
-table.version-chart th.y24q3::after {
+table.version-chart th.y24q4::after {
content: "Latest"
}
/* draw a focus rectangle around the latest release column */
-table.version-chart th.y24q3 {
+table.version-chart th.y24q4 {
border-top: 2px solid #e06666 !important;
border-left: 2px solid #e06666 !important;
border-right: 2px solid #e06666 !important;
}
-table.version-chart td.y24q3 {
+table.version-chart td.y24q4 {
font-weight: bold;
border-left: 2px solid #e06666 !important;
border-right: 2px solid #e06666 !important;
}
-table.version-chart tr:last-child td.y24q3 {
+table.version-chart tr:last-child td.y24q4 {
border-bottom: 2px solid #e06666 !important;
}
/* future release columns */
-table.version-chart td:not(:has(~ .y24q3)):not(.y24q3) {
+table.version-chart td:not(:has(~ .y24q4)):not(.y24q4) {
font-style: italic;
}
diff --git a/content/news/2024-12-04.md b/content/news/2024-12-04.md
new file mode 100644
index 000000000..8679ee36c
--- /dev/null
+++ b/content/news/2024-12-04.md
@@ -0,0 +1,77 @@
++++
+title = "Changes announced December 4, 2024"
+linkTitle = "December 4, 2024"
+toc_hide = "true"
+description = "Changes announced for Protocol Buffers on December 4, 2024."
+type = "docs"
++++
+
+We are planning to modify the Protobuf debug APIs (including Protobuf
+AbslStringify, `proto2::ShortFormat`, `proto2::Utf8Format`,
+`Message::DebugString`, `Message::ShortDebugString`, `Message::Utf8DebugString`)
+in v30 to redact sensitive fields annotated by `debug_redact`; the outputs of
+these APIs will contain a per-process randomized prefix, and so will no longer
+be parseable by Protobuf TextFormat Parsers.
+
+## Motivation
+
+Currently Protobuf debug APIs print every field in a proto into human-readable
+formats. This may lead to privacy incidents where developers accidentally log
+Protobuf debug outputs containing sensitive fields.
+
+## How to Annotate Sensitive Fields
+
+There are two ways to mark fields sensitive:
+
+* Mark a field with the field option `debug_redact = true`, directly.
+
+ ```proto
+ message Foo {
+ optional string secret = 1 [debug_redact = true];
+ }
+ ```
+
+* If you have already defined a field annotation of type Enum by extending
+ `proto2.FieldOptions`, and certain values of this annotation are used to
+ annotate fields you would like to redact, then you can annotate these values
+ with `debug_redact = true`. All the fields that have been annotated with
+ such values will be redacted.
+
+ ```proto
+ package my.package;
+
+ extend proto2.FieldOptions {
+ # The existing field annotation
+ optional ContentType content_type = 1234567;
+ };
+
+ enum ContentType {
+ PUBLIC = 0;
+ SECRET = 1 [debug_redact = true];
+ };
+
+ message Foo {
+ # will not be redacted
+ optional string public_info = 1 [
+ (my.package.content_type) = PUBLIC
+ ];
+ # will be redacted
+ optional string secret = 1 [
+ (my.package.content_type) = SECRET
+ ];
+ }
+ ```
+
+## New Debug Format
+
+Compared to the existing debug format, the new debug format has two major
+differences:
+
+* The sensitive fields annotated with `debug_redact` are redacted
+ automatically in the output formats
+* The output formats will contain a per-process randomized prefix, which will
+ make them no longer be parsable by TextFormat parsers.
+
+Note that the second change is true regardless of whether the proto contains
+sensitive fields or not, which ensures that any debug output always cannot be
+deserialized regardless of the proto content.
diff --git a/content/news/_index.md b/content/news/_index.md
index 489aa446a..f60a38c98 100644
--- a/content/news/_index.md
+++ b/content/news/_index.md
@@ -20,6 +20,8 @@ New news topics will also be published to the
The following news topics provide information in the reverse order in which it
was released.
+* [December 4, 2024](/news/2024-12-04) - `DebugString`
+ replaced
* [November 7, 2024](/news/2024-11-07) - More breaking
changes in the upcoming 30.x release
* [October 2, 2024](/news/2024-10-02) - Breaking
diff --git a/content/news/v30.md b/content/news/v30.md
index 723b3d704..da9d2e2c4 100644
--- a/content/news/v30.md
+++ b/content/news/v30.md
@@ -43,6 +43,18 @@ dependencies.
If you use installed packages, you won't be affected. It could break some CMake
workflows.
+### Modify Debug APIs to Redact Sensitive Fields {#debug-redaction}
+
+We are planning to modify the Protobuf debug APIs (including Protobuf
+AbslStringify, `proto2::ShortFormat`, `proto2::Utf8Format`,
+`Message::DebugString`, `Message::ShortDebugString`, `Message::Utf8DebugString`)
+in v30 to redact sensitive fields annotated by `debug_redact`; the outputs of
+these APIs will contain a per-process randomized prefix, and so will no longer
+be parseable by Protobuf TextFormat Parsers.
+
+Read more about this in the
+[news article released November 21, 2024](/news/2024-11-21).
+
### Remove Deprecated APIs {#remove-deprecated}
v30 will remove the following public runtime APIs, which have been marked
diff --git a/content/programming-guides/deserialize-debug.md b/content/programming-guides/deserialize-debug.md
new file mode 100644
index 000000000..26fe363cd
--- /dev/null
+++ b/content/programming-guides/deserialize-debug.md
@@ -0,0 +1,120 @@
++++
+title = "Deserializing Debug Proto Representations"
+weight = 89
+description = "How to log debugging information in Protocol Buffers."
+type = "docs"
++++
+
+From version 29.x, `DebugString` APIs (`proto2::DebugString`,
+`proto2::ShortDebugString`, `proto2::Utf8DebugString`) are deprecated.
+DebugString users should migrate to some Abseil string functions (such as
+`absl::StrCat`, `absl::StrFormat`, `absl::StrAppend`, AND `absl::Substitute`),
+Abseil logging API, and some Protobuf APIs (`proto2::ShortFormat`,
+`proto2::Utf8Format`) to automatically convert proto arguments into a new
+debugging format .
+
+Unlike the Protobuf DebugString output format, the new debugging format
+automatically redacts sensitive fields by replacing their values with the string
+"[REDACTED]" (without the quotation marks). In
+addition, to ensure that this new output format cannot be deserialized by
+Protobuf TextFormat parsers, regardless of whether the underlying proto contains
+SPII fields, we add a set of randomized links pointing to this article
+and a randomized-length whitespace sequence. The new debugging format looks as
+follows:
+
+```none
+go/nodeserialize
+spii_field: [REDACTED]
+normal_field: "value"
+```
+
+Note that the new debugging format is only different from the output format of
+DebugString format in two ways:
+
+* The URL prefix
+* The values of SPII fields are replaced by
+ "[REDACTED]" (without the quotes)
+
+The new debugging format never removes any field names; it only replaces the
+value with
+"[REDACTED]" if the field is considered sensitive.
+**If you don't see certain fields in the output, it is because those fields are
+not set in the proto.**
+
+**Tip:** If you see only the URL and nothing else, your proto is empty!
+
+## Why is this URL here?
+
+We want to make sure nobody deserializes human-readable representations of a
+protobuf message intended for humans debugging a system. Historically,
+`.DebugString()` and `TextFormat` were interchangeable, and existing systems use
+DebugString to transport and store data.
+
+We want to make sure sensitive data does not accidentally end up in logs.
+Therefore, we are transparently redacting some field values from protobuf
+messages before turning them into a string
+("[REDACTED]"). This reduces the security & privacy
+risk of accidental logging, but risks data loss if other systems deserialize
+your message. To address this risk, we are intentionally splitting the
+machine-readable TextFormat from the human-readable debug format to be used in
+log messages.
+
+### Why are there links in my web page? Why is my code producing this new "debug representation"?
+
+This is intentional, to make the "debug representation" of your protos
+(produced, for example, by logging) incompatible with TextFormat. We want to
+prevent anyone from depending on debugging mechanisms to transport data between
+programs. Historically, the debug format (generated by the DebugString APIs) and
+TextFormat have been incorrectly used in a interchangeable fashion. We hope this
+intentional effort will prevent that going forward.
+
+We intentionally picked a link over less visible format changes to get an
+opportunity to provide context. This might stand out in UIs, such as if you
+display status information on a table in a webpage. You may use
+`TextFormat::PrintToString` instead, which will not redact any information and
+preserves formatting. However, use this API cautiously -- there are no built in
+protections. As a rule of thumb, if you are writing data to debug logs, or
+producing status messages, you should continue to use the Debug Format with the
+link. Even if you are currently not handling sensitive data, keep in mind that
+systems can change and code gets re-used.
+
+### I tried converting this message into TextFormat, but I noticed the format changes every time my process restarts.
+
+This is intentional. Don't attempt to parse the output of this debug format. We
+reserve the right to change the syntax without notice. The debug format syntax
+randomly changes per process to prevent inadvertent dependencies. If a syntactic
+change in the debug format would break your system, chances are you shouldn't
+use the debug representation of a proto.
+
+## FAQ
+
+### Can I Just Use TextFormat Everywhere?
+
+Don't use TextFormat for producing log messages. This will bypass all built-in
+protections, and you risk accidentally logging sensitive information. Even if
+your systems are currently not handling any sensitive data, this can change in
+the future.
+
+Distinguish logs from information that's meant for further processing by other
+systems by using either the debug representation or TextFormat as appropriate.
+
+### I Want to Write Configuration Files That Need to Be Both Human-Readable And Machine-Readable
+
+For this use case, you can use TextFormat explicitly. You are responsible for
+making sure your configuration files don't contain any PII.
+
+### I Am Writing a Unit Test, and Want to Compare Debugstring in a Test Assertion
+
+If you want to compare protobuf values, use `MessageDifferencer` like in the
+following:
+
+```cpp
+using google::protobuf::util::MessageDifferencer;
+...
+MessageDifferencer diff;
+...
+diff.Compare(foo, bar);
+```
+
+Besides ignoring formatting and field order differences, you will also get
+better error messages.
diff --git a/content/programming-guides/dos-donts.md b/content/programming-guides/dos-donts.md
index eebb91f4c..e1bc96541 100644
--- a/content/programming-guides/dos-donts.md
+++ b/content/programming-guides/dos-donts.md
@@ -183,7 +183,7 @@ from repeated to scalar will result in the last deserialized value "winning."
Going from scalar to repeated is OK in proto2 and in proto3 with
`[packed=false]` because for binary serialization the scalar value becomes a
-one-element list .
+one-element list.
diff --git a/content/reference/cpp/cpp-generated.md b/content/reference/cpp/cpp-generated.md
index 443a9297e..6b3cd9194 100644
--- a/content/reference/cpp/cpp-generated.md
+++ b/content/reference/cpp/cpp-generated.md
@@ -409,21 +409,21 @@ enum Bar {
For either of these field definitions:
```proto
-optional Bar foo = 1;
-required Bar foo = 1;
+optional Bar bar = 1;
+required Bar bar = 1;
```
The compiler will generate the following accessor methods:
-- `bool has_foo() const`: Returns `true` if the field is set.
-- `Bar foo() const`: Returns the current value of the field. If the field is
+- `bool has_bar() const`: Returns `true` if the field is set.
+- `Bar bar() const`: Returns the current value of the field. If the field is
not set, returns the default value.
-- `void set_foo(Bar value)`: Sets the value of the field. After calling this,
- `has_foo()` will return `true` and `foo()` will return `value`. In debug
+- `void set_bar(Bar value)`: Sets the value of the field. After calling this,
+ `has_bar()` will return `true` and `bar()` will return `value`. In debug
mode (i.e. NDEBUG is not defined), if `value` does not match any of the
values defined for `Bar`, this method will abort the process.
-- `void clear_foo()`: Clears the value of the field. After calling this,
- `has_foo()` will return `false` and `foo()` will return the default value.
+- `void clear_bar()`: Clears the value of the field. After calling this,
+ `has_bar()` will return `false` and `bar()` will return the default value.
### Implicit Presence Enum Fields (proto3) {#implicit-enum}
@@ -440,17 +440,17 @@ enum Bar {
For this field definition:
```proto
-Bar foo = 1; // no field label specified, defaults to implicit presence.
+Bar bar = 1; // no field label specified, defaults to implicit presence.
```
The compiler will generate the following accessor methods:
-- `Bar foo() const`: Returns the current value of the field. If the field is
+- `Bar bar() const`: Returns the current value of the field. If the field is
not set, returns the default value (0).
-- `void set_foo(Bar value)`: Sets the value of the field. After calling this,
- `foo()` will return `value`.
-- `void clear_foo()`: Clears the value of the field. After calling this,
- `foo()` will return the default value.
+- `void set_bar(Bar value)`: Sets the value of the field. After calling this,
+ `bar()` will return `value`.
+- `void clear_bar()`: Clears the value of the field. After calling this,
+ `bar()` will return the default value.
### Optional Embedded Message Fields (proto2 and proto3) {#embeddedmessage}
@@ -464,35 +464,35 @@ For any of these field definitions:
```proto
//proto2
-optional Bar foo = 1;
-required Bar foo = 1;
+optional Bar bar = 1;
+required Bar bar = 1;
//proto3
-Bar foo = 1;
+Bar bar = 1;
```
The compiler will generate the following accessor methods:
-- `bool has_foo() const`: Returns `true` if the field is set.
-- `const Bar& foo() const`: Returns the current value of the field. If the
+- `bool has_bar() const`: Returns `true` if the field is set.
+- `const Bar& bar() const`: Returns the current value of the field. If the
field is not set, returns a `Bar` with none of its fields set (possibly
`Bar::default_instance()`).
-- `Bar* mutable_foo()`: Returns a pointer to the mutable `Bar` object that
+- `Bar* mutable_bar()`: Returns a pointer to the mutable `Bar` object that
stores the field's value. If the field was not set prior to the call, then
the returned `Bar` will have none of its fields set (i.e. it will be
- identical to a newly-allocated `Bar`). After calling this, `has_foo()` will
- return `true` and `foo()` will return a reference to the same instance of
+ identical to a newly-allocated `Bar`). After calling this, `has_bar()` will
+ return `true` and `bar()` will return a reference to the same instance of
`Bar`.
-- `void clear_foo()`: Clears the value of the field. After calling this,
- `has_foo()` will return `false` and `foo()` will return the default value.
-- `void set_allocated_foo(Bar* bar)`: Sets the `Bar` object to the field and
+- `void clear_bar()`: Clears the value of the field. After calling this,
+ `has_bar()` will return `false` and `bar()` will return the default value.
+- `void set_allocated_bar(Bar* bar)`: Sets the `Bar` object to the field and
frees the previous field value if it exists. If the `Bar` pointer is not
`NULL`, the message takes ownership of the allocated `Bar` object and
- `has_foo()` will return `true`. Otherwise, if the `Bar` is `NULL`, the
- behavior is the same as calling `clear_foo()`.
-- `Bar* release_foo()`: Releases the ownership of the field and returns the
+ `has_bar()` will return `true`. Otherwise, if the `Bar` is `NULL`, the
+ behavior is the same as calling `clear_bar()`.
+- `Bar* release_bar()`: Releases the ownership of the field and returns the
pointer of the `Bar` object. After calling this, caller takes the ownership
- of the allocated `Bar` object, `has_foo()` will return `false`, and `foo()`
+ of the allocated `Bar` object, `has_bar()` will return `false`, and `bar()`
will return the default value.
### Repeated Numeric Fields {#repeatednumeric}
@@ -593,33 +593,33 @@ enum Bar {
For this field definition:
```proto
-repeated Bar foo = 1;
+repeated Bar bar = 1;
```
The compiler will generate the following accessor methods:
-- `int foo_size() const`: Returns the number of elements currently in the
+- `int bar_size() const`: Returns the number of elements currently in the
field. To check for an empty set, consider using the
[`empty()`](/reference/cpp/api-docs/google.protobuf.repeated_field#RepeatedPtrField)
method in the underlying `RepeatedField` instead of this method.
-- `Bar foo(int index) const`: Returns the element at the given zero-based
- index. Calling this method with index outside of [0, foo_size()) yields
+- `Bar bar(int index) const`: Returns the element at the given zero-based
+ index. Calling this method with index outside of [0, bar_size()) yields
undefined behavior.
-- `void set_foo(int index, Bar value)`: Sets the value of the element at the
+- `void set_bar(int index, Bar value)`: Sets the value of the element at the
given zero-based index. In debug mode (i.e. NDEBUG is not defined), if
`value` does not match any of the values defined for `Bar`, this method will
abort the process.
-- `void add_foo(Bar value)`: Appends a new element to the end of the field
+- `void add_bar(Bar value)`: Appends a new element to the end of the field
with the given value. In debug mode (i.e. NDEBUG is not defined), if `value`
does not match any of the values defined for `Bar`, this method will abort
the process.
-- `void clear_foo()`: Removes all elements from the field. After calling this,
- `foo_size()` will return zero.
-- `const RepeatedField& foo() const`: Returns the underlying
+- `void clear_bar()`: Removes all elements from the field. After calling this,
+ `bar_size()` will return zero.
+- `const RepeatedField& bar() const`: Returns the underlying
[`RepeatedField`](/reference/cpp/api-docs/google.protobuf.repeated_field#RepeatedField)
that stores the field's elements. This container class provides STL-like
iterators and other methods.
-- `RepeatedField* mutable_foo()`: Returns a pointer to the underlying
+- `RepeatedField* mutable_bar()`: Returns a pointer to the underlying
mutable `RepeatedField` that stores the field's elements. This container
class provides STL-like iterators and other methods.
@@ -634,27 +634,27 @@ message Bar {}
For this field definitions:
```proto
-repeated Bar foo = 1;
+repeated Bar bar = 1;
```
The compiler will generate the following accessor methods:
-- `int foo_size() const`: Returns the number of elements currently in the
+- `int bar_size() const`: Returns the number of elements currently in the
field. To check for an empty set, consider using the
[`empty()`](/reference/cpp/api-docs/google.protobuf.repeated_field#RepeatedPtrField)
method in the underlying `RepeatedField` instead of this method.
-- `const Bar& foo(int index) const`: Returns the element at the given
- zero-based index. Calling this method with index outside of [0, foo_size())
+- `const Bar& bar(int index) const`: Returns the element at the given
+ zero-based index. Calling this method with index outside of [0, bar_size())
yields undefined behavior.
-- `Bar* mutable_foo(int index)`: Returns a pointer to the mutable `Bar` object
+- `Bar* mutable_bar(int index)`: Returns a pointer to the mutable `Bar` object
that stores the value of the element at the given zero-based index. Calling
- this method with index outside of [0, foo_size()) yields undefined behavior.
-- `Bar* add_foo()`: Adds a new element to the end of the field and returns a
+ this method with index outside of [0, bar_size()) yields undefined behavior.
+- `Bar* add_bar()`: Adds a new element to the end of the field and returns a
pointer to it. The returned `Bar` is mutable and will have none of its
fields set (i.e. it will be identical to a newly-allocated `Bar`).
-- `void clear_foo()`: Removes all elements from the field. After calling this,
- `foo_size()` will return zero.
-- `const RepeatedPtrField& foo() const`: Returns the underlying
+- `void clear_bar()`: Removes all elements from the field. After calling this,
+ `bar_size()` will return zero.
+- `const RepeatedPtrField& bar() const`: Returns the underlying
[`RepeatedPtrField`](/reference/cpp/api-docs/google.protobuf.repeated_field#RepeatedPtrField)
that stores the field's elements. This container class provides STL-like
iterators and other methods.
@@ -777,28 +777,28 @@ For the [oneof](#oneof) field definition:
```proto
oneof example_name {
- Bar foo = 1;
+ Bar bar = 1;
...
}
```
The compiler will generate the following accessor methods:
-- `bool has_foo() const`: Returns `true` if oneof case is `kFoo`.
-- `Bar foo() const`: Returns the current value of the field if oneof case is
- `kFoo`. Otherwise, returns the default value.
-- `void set_foo(Bar value)`:
+- `bool has_bar() const`: Returns `true` if oneof case is `kBar`.
+- `Bar bar() const`: Returns the current value of the field if oneof case is
+ `kBar`. Otherwise, returns the default value.
+- `void set_bar(Bar value)`:
- If any other oneof field in the same oneof is set, calls
`clear_example_name()`.
- - Sets the value of this field and sets the oneof case to `kFoo`.
- - `has_foo()` will return `true`, `foo()` will return `value` and
- `example_name_case()` will return `kFoo`.
+ - Sets the value of this field and sets the oneof case to `kBar`.
+ - `has_bar()` will return `true`, `bar()` will return `value` and
+ `example_name_case()` will return `kBar`.
- In debug mode (i.e. NDEBUG is not defined), if `value` does not match
any of the values defined for `Bar`, this method will abort the process.
-- `void clear_foo()`:
- - Nothing will be changed if the oneof case is not `kFoo`.
- - If the oneof case is `kFoo`, clears the value of the field and the oneof
- case. `has_foo()` will return `false`, `foo()` will return the default
+- `void clear_bar()`:
+ - Nothing will be changed if the oneof case is not `kBar`.
+ - If the oneof case is `kBar`, clears the value of the field and the oneof
+ case. `has_bar()` will return `false`, `bar()` will return the default
value and `example_name_case()` will return `EXAMPLE_NAME_NOT_SET`.
### Oneof Embedded Message Fields {#oneof-embedded}
@@ -813,47 +813,47 @@ For the [oneof](#oneof) field definition:
```proto
oneof example_name {
- Bar foo = 1;
+ Bar bar = 1;
...
}
```
The compiler will generate the following accessor methods:
-- `bool has_foo() const`: Returns true if oneof case is `kFoo`.
-- `const Bar& foo() const`: Returns the current value of the field if oneof
- case is `kFoo`. Otherwise, returns a Bar with none of its fields set
+- `bool has_bar() const`: Returns true if oneof case is `kBar`.
+- `const Bar& bar() const`: Returns the current value of the field if oneof
+ case is `kBar`. Otherwise, returns a Bar with none of its fields set
(possibly `Bar::default_instance()`).
-- `Bar* mutable_foo()`:
+- `Bar* mutable_bar()`:
- If any other oneof field in the same oneof is set, calls
`clear_example_name()`.
- - Sets the oneof case to `kFoo` and returns a pointer to the mutable Bar
- object that stores the field's value. If the oneof case was not `kFoo`
+ - Sets the oneof case to `kBar` and returns a pointer to the mutable Bar
+ object that stores the field's value. If the oneof case was not `kBar`
prior to the call, then the returned Bar will have none of its fields
set (i.e. it will be identical to a newly-allocated Bar).
- - After calling this, `has_foo()` will return `true`, `foo()` will return
+ - After calling this, `has_bar()` will return `true`, `bar()` will return
a reference to the same instance of `Bar` and `example_name_case()` will
- return `kFoo`.
-- `void clear_foo()`:
- - Nothing will be changed if the oneof case is not `kFoo`.
- - If the oneof case equals `kFoo`, frees the field and clears the oneof
- case. `has_foo()` will return `false`, `foo()` will return the default
+ return `kBar`.
+- `void clear_bar()`:
+ - Nothing will be changed if the oneof case is not `kBar`.
+ - If the oneof case equals `kBar`, frees the field and clears the oneof
+ case. `has_bar()` will return `false`, `bar()` will return the default
value and `example_name_case()` will return `EXAMPLE_NAME_NOT_SET`.
-- `void set_allocated_foo(Bar* bar)`:
+- `void set_allocated_bar(Bar* bar)`:
- Calls `clear_example_name()`.
- If the `Bar` pointer is not `NULL`: Sets the `Bar` object to the field
- and sets the oneof case to `kFoo`. The message takes ownership of the
- allocated `Bar` object, has_foo() will return true and
- `example_name_case()` will return `kFoo`.
- - If the pointer is `NULL`, `has_foo()` will return `false` and
+ and sets the oneof case to `kBar`. The message takes ownership of the
+ allocated `Bar` object, has_bar() will return true and
+ `example_name_case()` will return `kBar`.
+ - If the pointer is `NULL`, `has_bar()` will return `false` and
`example_name_case()` will return `EXAMPLE_NAME_NOT_SET`. (The behavior
is like calling `clear_example_name()`)
-- `Bar* release_foo()`:
- - Returns `NULL` if oneof case is not `kFoo`.
- - If the oneof case is `kFoo`, clears the oneof case, releases the
+- `Bar* release_bar()`:
+ - Returns `NULL` if oneof case is not `kBar`.
+ - If the oneof case is `kBar`, clears the oneof case, releases the
ownership of the field and returns the pointer of the `Bar` object.
After calling this, caller takes the ownership of the allocated `Bar`
- object, `has_foo()` will return `false`, `foo()` will return the default
+ object, `has_bar()` will return `false`, `bar()` will return the default
value and `example_name_case()` will return `EXAMPLE_NAME_NOT_SET`.
### Map Fields {#map}
diff --git a/content/reference/go/size.md b/content/reference/go/size.md
index d04ae4959..a4b0868de 100644
--- a/content/reference/go/size.md
+++ b/content/reference/go/size.md
@@ -44,8 +44,8 @@ quick fix to your pipeline:
```go {highlight="context:1,proto.Size,1"}
func (*beamFn) ProcessElement(key string, value []byte, emit func(proto.Message)) {
task := produceWorkTask(value)
- if proto.Size(task) > 100 * 1024 * 1024 {
- // Skip every work task over 100 MB to not overwhelm
+ if proto.Size(task) > 500 * 1024 * 1024 {
+ // Skip every work task over 500 MB to not overwhelm
// the brittle downstream system.
return
}
diff --git a/content/reference/protobuf/proto2-spec.md b/content/reference/protobuf/proto2-spec.md
index ea5264bb5..6d85415b6 100644
--- a/content/reference/protobuf/proto2-spec.md
+++ b/content/reference/protobuf/proto2-spec.md
@@ -272,6 +272,9 @@ extensions 100 to 199;
extensions 4, 20 to max;
```
+For more on this topic, see
+[Extension Declarations](/programming-guides/extension_declarations).
+
### Reserved
Reserved declares a range of field numbers or field names in a message that can