Commit graph

1482 commits

Author SHA1 Message Date
Runze Wang
be53faf37d internal change
PiperOrigin-RevId: 930072020
2026-06-10 14:17:37 -07:00
Jie Luo
e86e536349 Change Python DescriptorDatabase FindFileContainingSymbol() to accept leading "." to match DescriptorPool and other languages
PiperOrigin-RevId: 929451066
2026-06-09 15:58:00 -07:00
Israel Blancas
b6548fc510 python: mark proto_builder sha1 as non-security use (#27473)
Fixes #27472

Closes #27473

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/27473 from iblancasa:27472 0ab662a73b
PiperOrigin-RevId: 929221750
2026-06-09 08:53:29 -07:00
Charlie Beattie
593ab176d6 Faster Python cpp protos assignment to bytes/string fields.
PiperOrigin-RevId: 928459028
2026-06-08 03:32:33 -07:00
Charlie Beattie
2906b1e81b Internal change.
PiperOrigin-RevId: 927241088
2026-06-05 05:35:17 -07:00
Charlie Beattie
b6b55cc264 Internal change.
PiperOrigin-RevId: 927147774
2026-06-05 01:38:24 -07:00
Runze Wang
eebe9b7737 [py/C++] Implement Make GetOptions() return immutable options. C++ will raise a TypeError when options returned GetOptions() by is mutated.
PiperOrigin-RevId: 926215827
2026-06-03 13:10:50 -07:00
Runze Wang
f5738bb5f0 [py/pure python] Implement Make GetOptions() return immutable options. Raise a TypeError when options returned GetOptions() by is mutated.
PiperOrigin-RevId: 926114776
2026-06-03 10:20:31 -07:00
Mike Kruskal
ad842574d8 Automated Code Change
PiperOrigin-RevId: 925070778
2026-06-01 20:28:56 -07:00
Hong Shin
99efd19cb0 json/python: remove pool arg from _GetJsonEnumValueOption
PiperOrigin-RevId: 925012500
2026-06-01 17:54:28 -07:00
Charlie Beattie
524871b9d1 Add Python repeated fields benchmarks.
PiperOrigin-RevId: 924877292
2026-06-01 13:22:33 -07:00
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
Joshua Haberman
8ff5d8ad3f Added free threading support to PyUpb_WeakMap
Previously we had a lock in the global object cache (an instance of `PyUpb_WeakMap`), but this CL refactors `PyUpb_WeakMap` to be internally synchronized.

We also add code to handle a tricky edge case that can occur when a dealloc operation races with lookup.  This implementation mirrors the code previously implemented in C++ (`PyWeakValueMap`).

PiperOrigin-RevId: 921534474
2026-05-26 10:13:14 -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
Jie Luo
f9e028f29f bazel 9 tests for csharp, hpb, objc, php, python, rust and upb
PiperOrigin-RevId: 918164613
2026-05-19 19:58:47 -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
Protobuf Team Bot
1eb2c7268d Automated Code Change
PiperOrigin-RevId: 910923991
2026-05-05 14:45:51 -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
Protobuf Team Bot
5ea7e147ea Internal change
PiperOrigin-RevId: 888231953
2026-03-23 12:46:13 -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
Protobuf Team Bot
9b38d6d9a1 Add decoding error details for UPB proto parsing failures.
PiperOrigin-RevId: 883263178
2026-03-13 11:42:08 -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
Hong Shin
e7465f100a py generate_docs: simplify copyright header
PiperOrigin-RevId: 882703990
2026-03-12 11:53:27 -07:00