Skip to content

codegen, descriptor: an extension of a message_set_wire_format message cannot have a number above 2^29 - 1 #702

Description

@iainmcgin
syntax = "proto2";
message Set {
  option message_set_wire_format = true;
  extensions 4 to max;
}
message Item {
  extend Set { optional Item ext = 1000000000; }
}

protoc accepts this file. A MessageSet carries the extension number as an int32 type_id, not in a tag, so protoc lifts the 2^29 - 1 bound for it:

  • max ends a MessageSet's extension range at i32::MAX (AdjustExtensionRangesWithMaxEndNumber, src/google/protobuf/compiler/parser.cc:889-892), so the largest number the range above admits is 2^31 - 2.
  • The range check uses i32::MAX as the bound for a MessageSet (ValidateExtensionRangeOptions, src/google/protobuf/descriptor.cc:8366-8369, :8384).
  • "Field numbers cannot be greater than 536870911" is skipped for an extension, and the comment gives MessageSet as the reason (descriptor.cc:6518-6526).

buffa rejects the file in two places:

  • Codegen: generate_one (buffa-codegen/src/extension.rs) calls impl_message::validated_field_number, which returns CodeGenError::Other("invalid field number: 1000000000") for every number above MAX_FIELD_NUMBER.
  • DescriptorPool: link_message (buffa-descriptor/src/pool.rs) accepts the range, because ExtensionRangeEndTooLarge exempts a MessageSet, and link_field then returns PoolError::InvalidFieldNumber for the extension, because its bound is MAX_FIELD_NUMBER for every field.

The runtime already handles such a number: message_set::merge_item (buffa/src/message_set.rs) accepts a type_id in [1, i32::MAX], and since #674 Extension::new accepts a number up to i32::MAX for this case.

Expected: both checks use i32::MAX as the bound when the field is an extension whose extendee has message_set_wire_format = true, and keep MAX_FIELD_NUMBER for every other field and extension. The check in link_field runs before the extendee is resolved, so the pool has to apply the bound in link_extension.

Activity

  1. Divyansh151005 commented on Oct 28, 2026

    @Divyansh151005
    Contributor

    Planning to fix the MessageSet extension field-number bound in buffa-descriptor (link_extension / link_field) and buffa-codegen (extension.rs), matching protoc's i32::MAX limit for extensions of message_set_wire_format messages. Will add targeted pool + codegen tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions