Commit graph

1054 commits

Author SHA1 Message Date
Kamil Monicz
e090f8ae77 Serialize length-prefixed protos once (#27252)
Avoid calling ByteSize() separately in serialize_length_prefixed(). The serialized payload already carries the exact length to prefix, so this keeps behavior intact while avoiding a duplicate serialization-sized pass.

Closes #27252

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/27252 from Zaczero:python-serialize-length-prefixed-once 8a4f60b4c7
PiperOrigin-RevId: 923539199
2026-05-29 12:19:19 -07:00
Runze Wang
12baad3caa internal change
PiperOrigin-RevId: 922907524
2026-05-28 12:21:38 -07:00
Hong Shin
7800571253 json/python: add support for custom json strings for enum values
PiperOrigin-RevId: 922729754
2026-05-28 06:17:20 -07:00
Charlie Beattie
6dac2de5b6 Remove possible use after free via Python Buffer Objects in MergeFromString.
PiperOrigin-RevId: 921681380
2026-05-26 14:27:25 -07:00
Charlie Beattie
f7c66578cc Add assign_bytes Benchmarks.
PiperOrigin-RevId: 919863834
2026-05-22 14:36:41 -07:00
Runze Wang
403d429eab [py/upb] Make GetOptions() return immutable options for scalar type. UPB will raise a TypeError when options returned GetOptions() by is mutated.
PiperOrigin-RevId: 918559519
2026-05-20 11:33:26 -07:00
Amer Elsheikh
5f77738be4 Create an enum_type_wrapper.pyi stub with DESCRIPTOR: EnumDescriptor
PiperOrigin-RevId: 914243299
2026-05-12 06:14:01 -07:00
Joshua Haberman
ac90873fac Add test for RepeatedCompositeContainer comparison with list.
This test highlights a behavioral difference where upb allows equality comparison between a RepeatedCompositeContainer and a Python list, while the cpp and python implementations raise a TypeError.

PiperOrigin-RevId: 912754358
2026-05-08 16:43:32 -07:00
Joshua Haberman
6cbc7593bf Fixed race in GetMessageClass/RegisterMessageClass under free threading.
The race condition was resolved by adding a mutex lock to all accesses of the cache.

PiperOrigin-RevId: 912595698
2026-05-08 10:47:54 -07:00
Oblivionsage
94df512b87 fix: check AssureWritable() return value at all call sites (#26390)
Fixes #26389

`AssureWritable()` returns `-1` on failure (OOM in `MutableMessage()`), but 13 call sites were ignoring this return value.

When `AssureWritable()` fails, `self->message` still points to the shared read-only default instance. Subsequent mutations (`MergeFrom`, `CopyFrom`, `Clear`, `SetField`, etc.) then corrupt the shared global default instance, affecting all messages of the same type.

Same bug class as the recent `FixupMessageAfterMerge` fix (ab14c0f8a).

Closes #26390

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/26390 from Oblivionsage:fix/check-assure-writable-return-value adbd20477e
PiperOrigin-RevId: 912044414
2026-05-07 10:59:13 -07:00
Protobuf Team Bot
66ee7113cf Automated rollback of commit 62074624a9.
PiperOrigin-RevId: 911144902
2026-05-06 00:07:32 -07:00
Joshua Haberman
62074624a9 [Py/C++ Optimization]: cache prototype in the CMessageClass
This avoids calling `GetPrototype()` every time a message is constructed, which would acquire a lock.

There is no need to look it up every time, because it will never change as long as the MessageFactory is alive.

PiperOrigin-RevId: 910918341
2026-05-05 14:35:54 -07:00
Protobuf Team Bot
af47fbb369 Improve serialization performance in the case of recursive maps in pure Python Protobuf.
PiperOrigin-RevId: 910887857
2026-05-05 13:45:18 -07:00
Protobuf Team Bot
5be0a43cd6 Avoid NULL pointer dereference in PyUpb_PyToUpbEnum if run with a malformed UTF-8 str (e.g. "\ud800")
Add test coverage of 'assign string to enum-typed field' in general (including this case). This appears to be accepted only Py-upb and not otherwise.

Fixes https://github.com/protocolbuffers/protobuf/issues/27106

PiperOrigin-RevId: 908148411
2026-04-30 07:01:58 -07:00
Protobuf Team Bot
cecbbf41e4 Add mutex protection to DescriptorPool caches.
This change introduces a FreeThreadingMutex to PyDescriptorPool to guard access to the descriptor_options and descriptor_features hash maps.

PiperOrigin-RevId: 908115178
2026-04-30 05:47:00 -07:00
Protobuf Team Bot
6cd6ca4116 Auto-format Py Proto python files.
PiperOrigin-RevId: 907755617
2026-04-29 13:40:58 -07:00
Runze Wang
3fca2336f8 This is a future breaking change.
PiperOrigin-RevId: 907076763
2026-04-28 11:12:07 -07:00
Amer Elsheikh
4a62481217 Make EnumTypeWrapper a metaclass during type checking.
PiperOrigin-RevId: 903954047
2026-04-22 11:36:53 -07:00
Runze Wang
c857f49224 Refactor container comparison function in py/C++ and py/upb to return enum instead of integer.
The new enum is:
```py
typedef enum {
  kPyUpb_CompareEqual, # formerly return value 1
  kPyUpb_CompareNotEqual, # formerly return value 0
  kPyUpb_CompareError, # formerly return value -1
} PyUpb_CompareResult;
```

PiperOrigin-RevId: 903510540
2026-04-21 17:21:22 -07:00
Joshua Haberman
e264a3aa3f Add a test to document that GetOptions() return values are mutable.
The test demonstrates that modifying the message options returned by GetOptions() is currently possible, which is an unintended side effect.

PiperOrigin-RevId: 903414364
2026-04-21 14:06:48 -07:00
Protobuf Team Bot
cfcc4337ae Py JSON: Fix issue with depth enforcement on Struct/Value WKT paths.
This just reroutes these calls back through the ConvertMessage path. This will have some trivial extra overhead but will necessarily routes back to the _ConvertStructMessage etc cases after enforcing a depth cap.

Fixes https://github.com/protocolbuffers/protobuf/issues/26736

Fixes https://github.com/protocolbuffers/protobuf/issues/26432

PiperOrigin-RevId: 903387883
2026-04-21 13:13:45 -07:00
Protobuf Team Bot
33e6ab172b Add comments to TextFormat documenting that its intended for human-in-the-loop usecases (not wire format).
In the cases where we historically didn't enforce a depth limit (C++ and Python) document that the default behavior having no depth limit is an intentional decision.

PiperOrigin-RevId: 903216142
2026-04-21 07:22:43 -07:00
Samuel Benzaquen
e6ee74af87 Updating version.json and repo version numbers to: 36.0-dev (#26991)
NOTE: This should be reviewed and imported via Copybara per the normal PR review process.

Closes #26991

PiperOrigin-RevId: 902788011
2026-04-20 13:14:04 -07:00
Runze Wang
78a09ada5c Fix RepeatedContainer_pop to raise IndexError for out-of-bounds indices.
The previous implementation of RepeatedContainer_pop would clamp the index to the last element if it was out of bounds. This change removes the index clamping, ensuring that pop() raises an IndexError when given an index that is out of range, matching the other 2 pyproto implementation as well as standard Python list behavior. Tests are added to confirm this corrected behavior.

This is the 5th bug listed in https://github.com/protocolbuffers/protobuf/issues/26596

PiperOrigin-RevId: 902737839
2026-04-20 11:30:37 -07:00
Sakura501
8abff6bb4b fix Python text_format by adding an optional recursion depth limit (#26604)
## Summary
- fix Python `text_format` by adding an optional recursion depth limit
- add `max_recursion_depth` to `Parse`, `Merge`, `ParseLines`, and `MergeLines`
- keep the default behavior unchanged for compatibility
- enforce the configured limit consistently across root parsing, nested submessages, and expanded `Any`
- add regression tests for explicit opt-in depth enforcement and the default compatibility path

## Context
Python `text_format` parsing recursively descends through `_MergeField()` and `_MergeMessageField()`, and can also recurse through expanded `Any` payloads. Without a shared parser-side depth guard, deeply nested input can recurse until Python raises `RecursionError` instead of a controlled protobuf `ParseError`.

For applications that parse untrusted textproto, that makes deep nesting a denial-of-service primitive.

## Fix
This change adds an optional `max_recursion_depth` parameter to the public Python text format parsing entry points.

When the option is set, parsing tracks message depth through a shared helper and raises `ParseError` once the configured limit is exceeded. When the option is not set, parsing keeps the historical unbounded behavior so existing callers remain compatible.

## Testing
- `BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 bazel test //python:text_format_test --test_output=errors`

Closes #26604

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/26604 from Sakura-501:fix-python-text-format-unbounded-recursion 235abcd492
PiperOrigin-RevId: 898014428
2026-04-10 20:33:59 -07:00
Protobuf Team Bot
f9821fcf4f Fix python SyntaxWarning
\( is not a valid escape sequence.

PiperOrigin-RevId: 895607647
2026-04-06 19:05:19 -07:00
Joshua Haberman
28e451233d Fix data race in CMessage lazy initialization for Python freethreading.
This change introduces a `LazyUniquePtr` class to manage the lazy initialization of `composite_fields` and `child_submessages` within `CMessage`. When Python's GIL is disabled, `LazyUniquePtr` uses atomic operations to ensure thread-safe initialization of these maps, preventing data races when multiple threads concurrently access fields that trigger their creation. A new test case is added to reproduce and verify the fix for a race condition in `GetFieldValue`.

We are forced to use placement new and placement delete for the `LazyUniquePtr` members, because the `CMessage` struct is currently not properly constructed or destroyed.  This makes the code a bit awkward, but changing the construction/destruction of CMessage seemed like too much to bite off in this CL.

PiperOrigin-RevId: 891703488
2026-03-30 07:23:10 -07:00
Protobuf Team Bot
7adc4b672d Change field_mask.py to avoid recursion
This makes it more robust in the face of deep fieldmasks.

Fixes https://github.com/protocolbuffers/protobuf/issues/26489

PiperOrigin-RevId: 889184207
2026-03-25 05:26:34 -07:00
Joshua Haberman
8c1a9a4b01 Fixed data race in Python Free Threading by removing unnecessary SetHasBitForRepeated() call.
This CL concerns the following functions in C++:

```c++
class Reflection {
  const Message& GetRepeatedMessage(const Message& message,
                                    const FieldDescriptor* field,
                                    int index) const;

  Message* MutableRepeatedMessage(Message* message,
                                  const FieldDescriptor* field,
                                  int index) const;
}
```

Suppose a Python program contains the following code:

```
def foo(msg: MyMessage):
  submsg = msg.repeated_foo[2]  # (A)
  if also_mutate:
    submsg.abc = 1              # (B)
```

For line (A), we currently call `MutableRepeatedMessage()` in C++ to
obtain the submessage pointer, because the resulting `submsg` object in
Python is a conceptually mutable object that will require a non-const
pointer if/when the program hits line (B).

The `MutableRepeatedMessage(Message* msg, ...)` function in C++
currently mutates `msg` by setting the hasbit of the repeated field. But
this seems unnecessary, as the function requires that the requested
sub-message already exists; it does not create a new message. So it
should not be necessary to touch the hasbit of the message, and a TGP
confirms that all tests pass if we remove this call.

Once the `SetHasBitForRepeated()` call is removed, the `MutableRepeatedMessage()`
function no longer actually mutates the `msg` argument. This makes it
effectively safe to call concurrently (ie. it will no longer trigger
Undefined Behavior in C++, and the TSAN errors will go away), which
is why it fixes the free threading test. But it leaves us in an odd
state where we are still passing a non-`const` pointer to the same
message to two functions concurrently, which is not allowed under a
normal thread-compatible contract.

An alternate solution would be to call `GetRepeatedMessage()` instead,
and `const_cast<>` away the const in the returned `const Message&`.
But this is also violates the contract: users should not be casting
away `const`.

The root cause of this odd situation is that
`MutableRepeatedMessage(Message* msg)` requires a non-`const` `msg` not
because it actually *mutates* `msg`, but because it is trying to
propagate the const-ness of `msg` to all of its children.  The proto API
generally guarantees that a const message prevents mutation of not just
the top-level message, but of the entire tree of messages. If someone
passes you a `const` message pointer, that is supposed to render the
entire tree of messages under it immutable through that pointer.

What we wish we could express in `MutableRepeatedMessage(Message* msg)`
is: "this function requires that `msg` is mutable, but this function
will not actually mutate it, and is therefore safe to call concurrently."
But there is no way of expressing this in C++.
PiperOrigin-RevId: 886830933
2026-03-20 09:29:13 -07:00
Protobuf Team Bot
3edd61508b Fix type annotation for FindAllExtensionNumbers() to be a list rather than the more general Iterator.
DescriptorPool has a strict expectation that this return type must be a list.

PiperOrigin-RevId: 885275177
2026-03-17 16:44:08 -07:00
Protobuf Team Bot
cbe6403761 Add type hints to descriptor_database.py.
This change adds type annotations to the methods and instance variables within the DescriptorDatabase class, as well as to the helper function _ExtractSymbols. Forward references are used for types from descriptor_pb2.

PiperOrigin-RevId: 884793323
2026-03-16 21:43:11 -07:00
Joshua Haberman
3b0cfbf0a9 Fixed data race when accessing Python fields in free threaded builds.
To do this, we need to make CMessage use thread-safe maps for its sub-object caches.

PiperOrigin-RevId: 884515030
2026-03-16 10:28:49 -07:00
Joshua Haberman
ab14c0f8ad Fixed a bug in msg.MergeFrom(msg2) in Python.
In `FixupMessageAfterMerge()`, the loop over fields was exiting the entire function if a mutable field was found, but this skips other fields that may need fixing up.

PiperOrigin-RevId: 882766354
2026-03-12 14:04:14 -07:00
Jie Luo
059dc7ed32 Fix NULL byte handling issue in Python Protobuf find symbols in pool
PiperOrigin-RevId: 882122977
2026-03-11 11:54:48 -07:00
Protobuf Team Bot
1c2af13202 Add missing upb_XXXDef_FindXXXByNameWithSize functions and index methods by name
PiperOrigin-RevId: 878471014
2026-03-04 07:06:24 -08:00
Mark Barolak
d875ed69b6 Cleanup:
* Remove unneeded "google/protobuf/stubs/common.h" includes
* Migrate uses of kuint64max over to the C++ standard std::numeric_limits<uint64_t>::max()

PiperOrigin-RevId: 875122434
2026-02-25 06:09:54 -08:00
Joshua Haberman
0ed798a0d2 Fixed race condition in free threaded builds related to the descriptor cache.
Prior to this CL, it was possible for the following sequence to occur:

|Thread 1|Thread 2|
|--------|--------|
|`obj = NewDescriptor(desc)`||
|`InsertCache(desc, obj)`||
|`Py_DECREF(obj)` (to 0)||
|`Dealloc(obj) {`||
||`LookupCache(desc) -> obj`|
||`Py_INCREF(obj)`|
|`  DeleteFromCache(obj)`||
|`}`||
||`Py_DECREF(obj)`|
||`Dealloc(obj)`|

This could lead to double-`Dealloc()` calls on a single object.  These calls could race, leading to TSAN failures.

We should look deeper into whether `GcTraverse()` and `GcClear()` still need critical sections.

PiperOrigin-RevId: 874084218
2026-02-23 08:30:44 -08:00
Jie Luo
b4c3fecb85 Add recursion guards for the following nested messages:
- map field for pure Python
- message_set_extension for Pure Python
- message_set_extension for UPB Python
https://github.com/protocolbuffers/protobuf/issues/25335

PiperOrigin-RevId: 868863633
2026-02-11 15:13:37 -08:00
Jie Luo
f10c1de25f Protobuf Python UPB Free Threading support.
Add obj_cache lock to pass current free threading tests on python upb.

PiperOrigin-RevId: 864903528
2026-02-03 09:04:20 -08:00
Aviral Garg
d2b001626d Fix Any recursion depth bypass in Python json_format.ParseDict (#25239)
This fixes a security vulnerability where nested google.protobuf.Any messages could bypass the max_recursion_depth limit, potentially leading to denial of service via stack overflow.

The root cause was that _ConvertAnyMessage() was calling itself recursively via methodcaller() for nested well-known types, bypassing the recursion depth tracking in ConvertMessage().

The fix routes well-known type parsing through ConvertMessage() to ensure proper recursion depth accounting for all message types including nested Any.

Fixes #25070

Closes #25239

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/25239 from aviralgarg05:fix-any-recursion-depth-bypass 3cbbcbea142593d3afd2ceba2db14b05660f62f4
PiperOrigin-RevId: 862740421
2026-01-29 10:17:18 -08:00
Mike Kruskal
e67b9cece7
Merge pull request #25438 from protocolbuffers/main-202601221720
Updating version.json and repo version numbers to: 35.0-dev
2026-01-22 10:01:36 -08:00
Etienne Pot
ea78297e0a Supports exporting int as int
PiperOrigin-RevId: 859620391
2026-01-22 08:35:26 -08:00
Protobuf Team Bot
8227cf1630 Updating version.json and repo version numbers to: 35-dev 2026-01-22 07:25:02 -08:00
Protobuf Team Bot
086093946d Automated Code Change
PiperOrigin-RevId: 858933397
2026-01-20 23:25:49 -08:00
Ionel Gog
7fd90b5314 Remove ref cycles introduced by self-calling nested functions.
PiperOrigin-RevId: 858670904
2026-01-20 11:11:02 -08:00
Jie Luo
c301c2ca28 Breaking Change: Remove deprecated UseDeprecatedLegacyJsonFieldConflicts()
https://protobuf.dev/news/2025-09-19/#cpp-remove-apis

PiperOrigin-RevId: 853477445
2026-01-07 17:35:56 -08:00
Mikita Belahlazau
4f076d951f Add metadata annotations for generated Python protobuf symbols.
The pyi generator now includes Kythe annotations for:
*   Extension field constants (e.g., `EXTENSION_FIELD`).
*   Field number constants (e.g., `STRING_FIELD_FIELD_NUMBER`).
*   `Create` methods in generated Stubby client classes.

These annotations allow the Python indexer to link these generated symbols back to their definitions in the `.proto` files.

PiperOrigin-RevId: 852971617
2026-01-06 16:05:56 -08:00
Protobuf Team Bot
ae67a4c195 Internal version update.
PiperOrigin-RevId: 852733884
2026-01-06 05:27:44 -08:00
Chris Kennelly
a70115f33f Breaking change: Add [[nodiscard]] to many APIs.
This covers two types of failures:
* Methods that are logically const and failure to consume the result indicates a bug
  (an unnecessary call, etc.)
* Methods that return significant errors (failure to parse, etc.) that should not be
  unintentionally ignored.

PiperOrigin-RevId: 852313694
2026-01-05 08:41:35 -08:00
Rachel Goldfinger
0404e66d8b Add conformance test for edition unstable
PiperOrigin-RevId: 850054867
2025-12-29 07:41:37 -08:00