You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fory.apache.org by ch...@apache.org on 2026/06/20 16:33:15 UTC

(fory-site) branch main updated (ecf13a2b98 -> 398a7c77f1)

This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git


    from ecf13a2b98 🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
     new 1b7cf0f942 🔄 synced local 'docs/guide/' with remote 'docs/guide/'
     new 398a7c77f1 🔄 synced local 'docs/specification/' with remote 'docs/specification/'

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 docs/guide/cpp/configuration.md                  | 70 +++++++++++++++++++++---
 docs/guide/csharp/configuration.md               | 60 ++++++++++++++++++--
 docs/guide/dart/configuration.md                 | 41 ++++++++++++--
 docs/guide/go/configuration.md                   | 56 +++++++++++++++++--
 docs/guide/java/configuration.md                 |  9 +++
 docs/guide/javascript/configuration.md           | 29 +++++++---
 docs/guide/kotlin/configuration.md               |  5 ++
 docs/guide/python/configuration.md               | 44 +++++++++++----
 docs/guide/rust/configuration.md                 | 38 +++++++++++--
 docs/guide/scala/configuration.md                |  5 ++
 docs/guide/swift/configuration.md                | 25 ++++++++-
 docs/guide/xlang/serialization.md                | 35 ++++++++++++
 docs/specification/java_serialization_spec.md    |  6 ++
 docs/specification/xlang_implementation_guide.md | 55 ++++++++++++++++++-
 docs/specification/xlang_serialization_spec.md   | 10 ++++
 15 files changed, 436 insertions(+), 52 deletions(-)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fory.apache.org
For additional commands, e-mail: commits-help@fory.apache.org


(fory-site) 02/02: 🔄 synced local 'docs/specification/' with remote 'docs/specification/'

Posted by ch...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git

commit 398a7c77f19e711d3e6406b114917b0b21392170
Author: chaokunyang <sh...@gmail.com>
AuthorDate: Sat Jun 20 16:33:10 2026 +0000

    🔄 synced local 'docs/specification/' with remote 'docs/specification/'
---
 docs/specification/java_serialization_spec.md    |  6 +++
 docs/specification/xlang_implementation_guide.md | 55 +++++++++++++++++++++++-
 docs/specification/xlang_serialization_spec.md   | 10 +++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/docs/specification/java_serialization_spec.md b/docs/specification/java_serialization_spec.md
index 609bae7001..607fffe772 100644
--- a/docs/specification/java_serialization_spec.md
+++ b/docs/specification/java_serialization_spec.md
@@ -410,6 +410,12 @@ Root kind codes:
 Class layers are encoded from parent to leaf. Field lists inside each layer use
 the field order defined above.
 
+Readers may reject a received TypeDef that exceeds runtime resource limits such
+as maximum metadata body bytes or maximum fields in one TypeDef. These limits
+are receive-side resource controls and do not change the TypeDef wire encoding,
+type identity, dynamic class loading, unknown-class handling, registration
+policy, or schema-evolution semantics.
+
 ### Field Info
 
 Each field is encoded as:
diff --git a/docs/specification/xlang_implementation_guide.md b/docs/specification/xlang_implementation_guide.md
index da68fd5859..d8fb205012 100644
--- a/docs/specification/xlang_implementation_guide.md
+++ b/docs/specification/xlang_implementation_guide.md
@@ -22,7 +22,7 @@ license: |
 ## Overview
 
 This guide describes the current xlang implementation ownership model used by
-the reference Java implementation and mirrored by the Dart implementation rewrite.
+the xlang runtimes.
 
 The wire format is defined by
 [Xlang Serialization Spec](xlang_serialization_spec.md). This document is about
@@ -403,6 +403,57 @@ are readable through the byte owner. Field-list allocation should happen after
 that body readability check and should not use a separate small initial-capacity
 cap as a security rule.
 
+Implementations should also bound received metadata bodies and struct field
+lists on the cold metadata parse path. `maxTypeMetaBytes` limits one encoded
+TypeDef or TypeMeta body, excluding the 8-byte header and any extended-size
+varint, and is checked before copying or decompressing that body.
+`maxTypeFields` limits the number of fields declared by one received struct
+metadata body and is checked before reserving or allocating the field list.
+These limits are runtime resource controls; they do not change wire encoding,
+type identity, dynamic loading, unknown-type behavior, deserialization policy,
+or schema-evolution semantics. Metadata cache hits and generated field readers
+remain hot paths and must not add work for these limits.
+
+Remote schema-version limits belong to the same cold metadata owner path.
+Header cache hits must skip the remaining metadata body and return cached
+metadata without schema-limit checks, hash revalidation, allocation, or policy
+work. On a header miss, keep the handling in one concrete owner path: prove and
+read the metadata body bytes, validate the body against its header, validate
+field counts, resolve the type through the existing registration and
+deserialization-policy checks, compare exact local metadata by original encoded
+bytes when applicable, check schema-version limits for non-local remote
+metadata, build the required read state, publish to the persistent metadata
+cache, and then record the schema count. Failed or incompatible metadata must
+not publish to the persistent cache and must not consume schema-version counts.
+
+Remote metadata whose encoded bytes exactly match the local registered metadata
+may use the local metadata without consuming the remote schema-version limit,
+after the existing type and deserialization-policy checks for selecting that
+local type have run. This exact-local bypass is not struct-only; it also applies
+to named enum, ext, and union metadata when those metadata bodies are present and
+match the local encoded bytes. Pure id-based enum, ext, and typed-union values
+do not carry TypeDef or TypeMeta bodies and must stay on the normal type-id plus
+user-type-id path. Compatible named enum, ext, and union metadata normally has
+one version, but it still counts against accepted remote metadata totals when it
+is sent as shared metadata and does not exactly match local metadata.
+`maxTypeFields` applies only to struct field lists.
+
+The exact-local candidate must be derived inside the metadata owner path from
+the decoded metadata identity: `userTypeId` for id-registered metadata, or
+`(namespace, typeName)` for name-registered metadata. Do not thread extra
+expected-type parameters through read callers solely for this check. This rule
+applies to every runtime. Java and Python may lazy-build the local encoded
+metadata only after this identity lookup selects a local class and the existing
+class, registration, and deserialization-policy checks for that class have run.
+
+When a statically declared compatible named enum, ext, or union field reads
+shared metadata, the decoded metadata must match the declared type id,
+namespace, and type name before the metadata owner publishes it to the
+persistent cache or records a schema count. Already accepted header or reference
+cache hits still skip the body and must not rerun body-hash, schema-limit, or
+registration checks, but the field reader must not treat metadata for a
+different declared named type as the current field's metadata.
+
 Skip paths do not need to materialize skipped values. Existing byte-skip
 operations should consume any available buffered prefix first, then skip or drop
 remaining stream bytes in bounded steps.
@@ -510,7 +561,7 @@ Two explicit pieces of state back xlang type metadata:
 
 - `MetaStringWriter` and `MetaStringReader` deduplicate and decode namespace
   and type-name strings
-- shared TypeDef write/read state tracks announced compatible struct metadata
+- shared TypeDef write/read state tracks announced TypeDef metadata
 
 Ownership rules:
 
diff --git a/docs/specification/xlang_serialization_spec.md b/docs/specification/xlang_serialization_spec.md
index cf46904344..71220b773c 100644
--- a/docs/specification/xlang_serialization_spec.md
+++ b/docs/specification/xlang_serialization_spec.md
@@ -651,6 +651,10 @@ After the type ID:
 - **UNION**: no extra bytes at this layer.
 - **LIST / SET / MAP / primitives**: no extra bytes at this layer.
 
+Pure id-based enum, ext, and typed-union values therefore do not carry a TypeDef
+body. Receive-side TypeDef resource limits apply only when the stream actually
+carries shared TypeDef metadata.
+
 `ARRAY (42)` is reserved for a future xlang extension for dedicated multi-dimensional arrays and
 is not used in current xlang streams.
 
@@ -743,6 +747,12 @@ Meta header byte for non-struct TypeDefs:
 - Bits 4-6: reserved (must be zero).
 - Bits 0-3: kind code.
 
+Readers may reject a received TypeDef that exceeds runtime resource limits such
+as maximum metadata body bytes or maximum fields in one struct TypeDef. These
+limits are receive-side resource controls and do not change TypeDef wire
+encoding, type identity, dynamic loading, unknown-type handling, registration
+policy, or schema-evolution semantics.
+
 Non-struct kind codes:
 
 - `0`: `ENUM`


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fory.apache.org
For additional commands, e-mail: commits-help@fory.apache.org


(fory-site) 01/02: 🔄 synced local 'docs/guide/' with remote 'docs/guide/'

Posted by ch...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git

commit 1b7cf0f94202124e9e545f02ef81fa8b37d8b8c1
Author: chaokunyang <sh...@gmail.com>
AuthorDate: Sat Jun 20 16:33:10 2026 +0000

    🔄 synced local 'docs/guide/' with remote 'docs/guide/'
---
 docs/guide/cpp/configuration.md        | 70 ++++++++++++++++++++++++++++++----
 docs/guide/csharp/configuration.md     | 60 ++++++++++++++++++++++++++---
 docs/guide/dart/configuration.md       | 41 +++++++++++++++++---
 docs/guide/go/configuration.md         | 56 ++++++++++++++++++++++++---
 docs/guide/java/configuration.md       |  9 +++++
 docs/guide/javascript/configuration.md | 29 ++++++++++----
 docs/guide/kotlin/configuration.md     |  5 +++
 docs/guide/python/configuration.md     | 44 +++++++++++++++------
 docs/guide/rust/configuration.md       | 38 +++++++++++++++---
 docs/guide/scala/configuration.md      |  5 +++
 docs/guide/swift/configuration.md      | 25 +++++++++++-
 docs/guide/xlang/serialization.md      | 35 +++++++++++++++++
 12 files changed, 367 insertions(+), 50 deletions(-)

diff --git a/docs/guide/cpp/configuration.md b/docs/guide/cpp/configuration.md
index 478e82f8fd..d617450041 100644
--- a/docs/guide/cpp/configuration.md
+++ b/docs/guide/cpp/configuration.md
@@ -115,6 +115,56 @@ This limits the maximum depth for nested polymorphic object serialization (e.g.,
 - **Increase**: For legitimate deeply nested data structures
 - **Decrease**: For stricter security requirements or shallow data structures
 
+### max_schema_versions_per_type(uint32_t)
+
+Set the maximum accepted remote metadata versions for one logical type.
+
+```cpp
+auto fory = Fory::builder()
+    .max_schema_versions_per_type(10)
+    .build();
+```
+
+**Default:** `10`
+
+### max_type_fields(uint32_t)
+
+Set the maximum fields accepted in one received remote struct metadata body.
+
+```cpp
+auto fory = Fory::builder()
+    .max_type_fields(512)
+    .build();
+```
+
+**Default:** `512`
+
+### max_type_meta_bytes(uint32_t)
+
+Set the maximum encoded body bytes accepted for one received TypeDef body,
+excluding the 8-byte header and any extended-size varint.
+
+```cpp
+auto fory = Fory::builder()
+    .max_type_meta_bytes(4096)
+    .build();
+```
+
+**Default:** `4096`
+
+### max_average_schema_versions_per_type(uint32_t)
+
+Set the average accepted remote metadata versions across accepted remote types.
+The effective global floor is `8192` schemas.
+
+```cpp
+auto fory = Fory::builder()
+    .max_average_schema_versions_per_type(3)
+    .build();
+```
+
+**Default:** `3`
+
 ### check_struct_version(bool)
 
 Enable/disable struct version checking.
@@ -150,13 +200,17 @@ auto fory = Fory::builder().build_thread_safe();  // Returns ThreadSafeFory
 
 ## Configuration Summary
 
-| Option                       | Description                             | Default |
-| ---------------------------- | --------------------------------------- | ------- |
-| `xlang(bool)`                | Use xlang mode                          | `true`  |
-| `compatible(bool)`           | Enable schema evolution                 | `true`  |
-| `track_ref(bool)`            | Enable reference tracking               | `true`  |
-| `max_dyn_depth(uint32_t)`    | Maximum nesting depth for dynamic types | `5`     |
-| `check_struct_version(bool)` | Enable struct version checking          | `false` |
+| Option                                           | Description                                       | Default |
+| ------------------------------------------------ | ------------------------------------------------- | ------- |
+| `xlang(bool)`                                    | Use xlang mode                                    | `true`  |
+| `compatible(bool)`                               | Enable schema evolution                           | `true`  |
+| `track_ref(bool)`                                | Enable reference tracking                         | `true`  |
+| `max_dyn_depth(uint32_t)`                        | Maximum nesting depth for dynamic types           | `5`     |
+| `max_type_fields(uint32_t)`                      | Max fields in one received struct metadata body   | `512`   |
+| `max_type_meta_bytes(uint32_t)`                  | Max encoded bytes in one received metadata body   | `4096`  |
+| `max_schema_versions_per_type(uint32_t)`         | Max remote metadata versions for one logical type | `10`    |
+| `max_average_schema_versions_per_type(uint32_t)` | Average remote metadata versions across types     | `3`     |
+| `check_struct_version(bool)`                     | Enable struct version checking                    | `false` |
 
 ## Security
 
@@ -166,6 +220,8 @@ Security-related configuration:
 - Use `check_struct_version(true)` with `compatible(false)` for intentional same-schema payloads.
 - Keep `max_dyn_depth(...)` as low as your model permits to reject unexpectedly deep polymorphic
   graphs.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
 - Prefer concrete fields over broad polymorphic fields for untrusted input.
 
 ## Related Topics
diff --git a/docs/guide/csharp/configuration.md b/docs/guide/csharp/configuration.md
index a158a6d5e3..e7c0c24d42 100644
--- a/docs/guide/csharp/configuration.md
+++ b/docs/guide/csharp/configuration.md
@@ -35,12 +35,16 @@ ThreadSafeFory threadSafe = Fory.Builder().BuildThreadSafe();
 
 `Fory.Builder().Build()` uses:
 
-| Option               | Default | Description                                  |
-| -------------------- | ------- | -------------------------------------------- |
-| `TrackRef`           | `false` | Reference tracking disabled                  |
-| `Compatible`         | `true`  | Compatible schema-evolution metadata enabled |
-| `CheckStructVersion` | `false` | Struct schema hash checks disabled           |
-| `MaxDepth`           | `20`    | Max dynamic nesting depth                    |
+| Option                            | Default | Description                                       |
+| --------------------------------- | ------- | ------------------------------------------------- |
+| `TrackRef`                        | `false` | Reference tracking disabled                       |
+| `Compatible`                      | `true`  | Compatible schema-evolution metadata enabled      |
+| `CheckStructVersion`              | `false` | Struct schema hash checks disabled                |
+| `MaxDepth`                        | `20`    | Max dynamic nesting depth                         |
+| `MaxTypeFields`                   | `512`   | Max fields in one received struct metadata body   |
+| `MaxTypeMetaBytes`                | `4096`  | Max encoded bytes in one received metadata body   |
+| `MaxSchemaVersionsPerType`        | `10`    | Max remote metadata versions for one logical type |
+| `MaxAverageSchemaVersionsPerType` | `3`     | Average remote metadata versions across types     |
 
 ## Builder Options
 
@@ -92,6 +96,48 @@ Fory fory = Fory.Builder()
 
 `value` must be greater than `0`.
 
+### `MaxTypeFields(int value)`
+
+Sets the maximum fields accepted in one received remote struct metadata body.
+
+```csharp
+Fory fory = Fory.Builder()
+    .MaxTypeFields(512)
+    .Build();
+```
+
+### `MaxTypeMetaBytes(int value)`
+
+Sets the maximum encoded body bytes accepted for one received TypeMeta body,
+excluding the 8-byte header and any extended-size varint.
+
+```csharp
+Fory fory = Fory.Builder()
+    .MaxTypeMetaBytes(4096)
+    .Build();
+```
+
+### `MaxSchemaVersionsPerType(int value)`
+
+Sets the maximum accepted remote metadata versions for one logical type.
+
+```csharp
+Fory fory = Fory.Builder()
+    .MaxSchemaVersionsPerType(10)
+    .Build();
+```
+
+### `MaxAverageSchemaVersionsPerType(int value)`
+
+Sets the average accepted remote metadata versions across accepted remote types.
+The effective global floor is `8192` schemas.
+
+```csharp
+Fory fory = Fory.Builder()
+    .MaxAverageSchemaVersionsPerType(3)
+    .Build();
+```
+
 ## Common Configurations
 
 ### Compatible service
@@ -127,6 +173,8 @@ Security-related configuration:
 - Register only the expected types before deserializing untrusted payloads.
 - Use `CheckStructVersion(true)` with `Compatible(false)` for intentional same-schema payloads.
 - Set `MaxDepth(...)` to reject unexpectedly deep dynamic object graphs.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
 - Prefer generated or registered concrete models over broad dynamic fields for untrusted input.
 
 ## Related Topics
diff --git a/docs/guide/dart/configuration.md b/docs/guide/dart/configuration.md
index f84ff49c2a..6a4c640f6a 100644
--- a/docs/guide/dart/configuration.md
+++ b/docs/guide/dart/configuration.md
@@ -34,6 +34,10 @@ final fory = Fory();
 // customize limits while keeping default compatible mode
 final fory = Fory(
   maxDepth: 512,
+  maxTypeFields: 512,
+  maxTypeMetaBytes: 4096,
+  maxSchemaVersionsPerType: 10,
+  maxAverageSchemaVersionsPerType: 3,
 );
 ```
 
@@ -82,13 +86,38 @@ Limits how deeply nested an object graph can be. Increase this if you have legit
 final fory = Fory(maxDepth: 128);
 ```
 
+### Remote schema metadata limits
+
+Compatible mode can receive remote metadata for schema evolution. These limits
+bound metadata size and accepted schema versions:
+
+```dart
+final fory = Fory(
+  maxTypeFields: 512,
+  maxTypeMetaBytes: 4096,
+  maxSchemaVersionsPerType: 10,
+  maxAverageSchemaVersionsPerType: 3,
+);
+```
+
+- `maxTypeFields` limits fields in one received struct metadata body.
+- `maxTypeMetaBytes` limits encoded body bytes in one received TypeMeta body, excluding the 8-byte
+  header and any extended-size varint.
+- `maxSchemaVersionsPerType` limits accepted remote metadata versions for one logical type.
+- `maxAverageSchemaVersionsPerType` limits the average across accepted remote types. The
+  effective global floor is `8192` schemas.
+
 ## Defaults
 
-| Option               | Default |
-| -------------------- | ------- |
-| `compatible`         | `true`  |
-| `checkStructVersion` | `false` |
-| `maxDepth`           | 256     |
+| Option                            | Default |
+| --------------------------------- | ------- |
+| `compatible`                      | `true`  |
+| `checkStructVersion`              | `false` |
+| `maxDepth`                        | 256     |
+| `maxTypeFields`                   | 512     |
+| `maxTypeMetaBytes`                | 4096    |
+| `maxSchemaVersionsPerType`        | 10      |
+| `maxAverageSchemaVersionsPerType` | 3       |
 
 ## Xlang Notes
 
@@ -105,6 +134,8 @@ Security-related configuration:
 - Register only the expected generated models before deserializing untrusted payloads.
 - Use `checkStructVersion: true` with `compatible: false` for intentional same-schema payloads.
 - Set `maxDepth` to reject unexpectedly deep payload shapes.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
 - Prefer generated schemas and explicit field metadata over broad dynamic fields for untrusted input.
 
 ## Related Topics
diff --git a/docs/guide/go/configuration.md b/docs/guide/go/configuration.md
index eb1aae5846..20d9012aee 100644
--- a/docs/guide/go/configuration.md
+++ b/docs/guide/go/configuration.md
@@ -33,12 +33,16 @@ f := fory.New(fory.WithXlang(true))
 
 Default settings:
 
-| Option     | Default | Description                                  |
-| ---------- | ------- | -------------------------------------------- |
-| TrackRef   | false   | Reference tracking disabled                  |
-| MaxDepth   | 20      | Maximum nesting depth                        |
-| IsXlang    | true    | Xlang mode enabled                           |
-| Compatible | true    | Compatible schema-evolution metadata enabled |
+| Option                          | Default | Description                                       |
+| ------------------------------- | ------- | ------------------------------------------------- |
+| TrackRef                        | false   | Reference tracking disabled                       |
+| MaxDepth                        | 20      | Maximum nesting depth                             |
+| IsXlang                         | true    | Xlang mode enabled                                |
+| Compatible                      | true    | Compatible schema-evolution metadata enabled      |
+| MaxTypeFields                   | 512     | Max fields in one received struct metadata body   |
+| MaxTypeMetaBytes                | 4096    | Max encoded bytes in one received metadata body   |
+| MaxSchemaVersionsPerType        | 10      | Max remote metadata versions for one logical type |
+| MaxAverageSchemaVersionsPerType | 3       | Average remote metadata versions across types     |
 
 ### With Options
 
@@ -47,6 +51,10 @@ f := fory.New(
     fory.WithXlang(true),
     fory.WithTrackRef(true),
     fory.WithMaxDepth(10),
+    fory.WithMaxTypeFields(512),
+    fory.WithMaxTypeMetaBytes(4096),
+    fory.WithMaxSchemaVersionsPerType(10),
+    fory.WithMaxAverageSchemaVersionsPerType(3),
 )
 ```
 
@@ -119,6 +127,40 @@ f := fory.New(fory.WithMaxDepth(30))
 - Protects against deeply nested, recursive structures or malicious data
 - Serialization fails with error when exceeded
 
+### WithMaxTypeFields
+
+Set the maximum fields accepted in one received remote struct metadata body:
+
+```go
+f := fory.New(fory.WithMaxTypeFields(512))
+```
+
+### WithMaxTypeMetaBytes
+
+Set the maximum encoded body bytes accepted for one received TypeDef body,
+excluding the 8-byte header and any extended-size varint:
+
+```go
+f := fory.New(fory.WithMaxTypeMetaBytes(4096))
+```
+
+### WithMaxSchemaVersionsPerType
+
+Set the maximum accepted remote metadata versions for one logical type:
+
+```go
+f := fory.New(fory.WithMaxSchemaVersionsPerType(10))
+```
+
+### WithMaxAverageSchemaVersionsPerType
+
+Set the average accepted remote metadata versions across accepted remote types.
+The effective global floor is `8192` schemas:
+
+```go
+f := fory.New(fory.WithMaxAverageSchemaVersionsPerType(3))
+```
+
 ### WithXlang
 
 Select the wire mode:
@@ -346,6 +388,8 @@ Security-related configuration:
 
 - Register only the expected structs before deserializing untrusted data.
 - Use `WithMaxDepth(...)` to reject unexpectedly deep payloads.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
 - Prefer concrete struct fields over broad `any` or interface-typed fields for untrusted input.
 
 ## Related Topics
diff --git a/docs/guide/java/configuration.md b/docs/guide/java/configuration.md
index a42da9f949..7b3ce60bf6 100644
--- a/docs/guide/java/configuration.md
+++ b/docs/guide/java/configuration.md
@@ -38,6 +38,10 @@ This page documents all configuration options available through `ForyBuilder`.
 | `registerGuavaTypes`                | Whether to pre-register Guava types such as `RegularImmutableMap`/`RegularImmutableList`. These types are not public API, but seem pretty stable.                                                                                                                                                                                                                                                                                                                    [...]
 | `requireClassRegistration`          | Disabling may allow unknown classes to be deserialized, potentially causing security risks.                                                                                                                                                                                                                                                                                                                                                                          [...]
 | `maxDepth`                          | Set max depth for deserialization, when depth exceeds, an exception will be thrown. This can be used to refuse deserialization DDOS attack.                                                                                                                                                                                                                                                                                                                          [...]
+| `maxTypeFields`                     | Maximum fields accepted in one received remote struct metadata body.                                                                                                                                                                                                                                                                                                                                                                                                 [...]
+| `maxTypeMetaBytes`                  | Maximum encoded body bytes accepted for one received TypeDef or TypeMeta body, excluding the 8-byte header and any extended-size varint.                                                                                                                                                                                                                                                                                                                             [...]
+| `maxSchemaVersionsPerType`          | Maximum accepted remote metadata versions for one logical type.                                                                                                                                                                                                                                                                                                                                                                                                      [...]
+| `maxAverageSchemaVersionsPerType`   | Average accepted remote metadata versions across all accepted remote types. The effective global floor is `8192` metadata entries.                                                                                                                                                                                                                                                                                                                                   [...]
 | `suppressClassRegistrationWarnings` | Whether to suppress class registration warnings. The warnings can be used for security audit, but may be annoying, this suppression will be enabled by default.                                                                                                                                                                                                                                                                                                      [...]
 | `metaShareEnabled`                  | Enables or disables meta share mode.                                                                                                                                                                                                                                                                                                                                                                                                                                 [...]
 | `scopedMetaShareEnabled`            | Scoped meta share focuses on a single serialization process. Metadata created or identified during this process is exclusive to it and is not shared with by other serializations.                                                                                                                                                                                                                                                                                   [...]
@@ -93,6 +97,11 @@ Security-related options:
 
 - `requireClassRegistration(true)` restricts deserialization to registered classes.
 - `withMaxDepth(...)` rejects unexpectedly deep object graphs.
+- `withMaxTypeFields(...)` and `withMaxTypeMetaBytes(...)` bound the field count
+  and encoded body size of one received remote metadata body.
+- `withMaxSchemaVersionsPerType(...)` and
+  `withMaxAverageSchemaVersionsPerType(...)` bound accepted remote metadata versions without
+  changing registration, dynamic loading, or schema-evolution semantics.
 - `withDeserializeUnknownClass(false)` avoids materializing unknown classes from metadata.
 - `checkJdkClassSerializable(true)` keeps the JDK serializability check for `java.*` classes.
 - Class registration warnings can be useful during security audits; use
diff --git a/docs/guide/javascript/configuration.md b/docs/guide/javascript/configuration.md
index e4a0fb3bd9..058bccf4b3 100644
--- a/docs/guide/javascript/configuration.md
+++ b/docs/guide/javascript/configuration.md
@@ -43,18 +43,26 @@ const fory = new Fory({
   ref: true,
   compatible: true,
   maxDepth: 100,
+  maxTypeFields: 512,
+  maxTypeMetaBytes: 4096,
+  maxSchemaVersionsPerType: 10,
+  maxAverageSchemaVersionsPerType: 3,
   hps,
 });
 ```
 
-| Option                     | Default | Description                                                                           |
-| -------------------------- | ------- | ------------------------------------------------------------------------------------- |
-| `ref`                      | `false` | Enable reference tracking for shared or circular object graphs                        |
-| `compatible`               | `true`  | Allow field additions/removals without breaking existing messages                     |
-| `maxDepth`                 | `50`    | Maximum nesting depth. Must be `>= 2`. Increase for deeply nested structures          |
-| `useSliceString`           | `false` | Optional string-reading optimization for Node.js. Leave at default unless benchmarked |
-| `hps`                      | unset   | Optional fast string helper from `@apache-fory/hps` (Node.js 20+)                     |
-| `hooks.afterCodeGenerated` | unset   | Callback to inspect the generated serializer code, useful for debugging               |
+| Option                            | Default | Description                                                                           |
+| --------------------------------- | ------- | ------------------------------------------------------------------------------------- |
+| `ref`                             | `false` | Enable reference tracking for shared or circular object graphs                        |
+| `compatible`                      | `true`  | Allow field additions/removals without breaking existing messages                     |
+| `maxDepth`                        | `50`    | Maximum nesting depth. Must be `>= 2`. Increase for deeply nested structures          |
+| `maxTypeFields`                   | `512`   | Maximum fields accepted in one received remote struct metadata body                   |
+| `maxTypeMetaBytes`                | `4096`  | Maximum encoded body bytes accepted for one received TypeMeta body                    |
+| `maxSchemaVersionsPerType`        | `10`    | Maximum accepted remote metadata versions for one logical type                        |
+| `maxAverageSchemaVersionsPerType` | `3`     | Average accepted remote metadata versions across accepted remote types                |
+| `useSliceString`                  | `false` | Optional string-reading optimization for Node.js. Leave at default unless benchmarked |
+| `hps`                             | unset   | Optional fast string helper from `@apache-fory/hps` (Node.js 20+)                     |
+| `hooks.afterCodeGenerated`        | unset   | Callback to inspect the generated serializer code, useful for debugging               |
 
 ## Reference Tracking
 
@@ -102,6 +110,11 @@ Security-related configuration:
 
 - Register only the expected schemas before deserializing untrusted payloads.
 - Set `maxDepth` for the maximum nesting depth your service accepts.
+- Keep `maxTypeFields` and `maxTypeMetaBytes` at their defaults unless the data
+  is not malicious and a trusted peer sends larger remote metadata.
+- Keep `maxSchemaVersionsPerType` and
+  `maxAverageSchemaVersionsPerType` at their defaults unless the data is not
+  malicious and a trusted peer sends many remote schema versions.
 - Prefer explicit `Type.struct(...)` schemas over `Type.any()` for untrusted input.
 - Pass `hps` only from the official package version you deploy with Fory.
 
diff --git a/docs/guide/kotlin/configuration.md b/docs/guide/kotlin/configuration.md
index 8c40d6ea6e..061f14a7f8 100644
--- a/docs/guide/kotlin/configuration.md
+++ b/docs/guide/kotlin/configuration.md
@@ -135,6 +135,8 @@ and any untrusted payload source:
 val fory = ForyKotlin.builder()
     .requireClassRegistration(true)
     .withMaxDepth(50)
+    .withMaxTypeFields(512)
+    .withMaxTypeMetaBytes(4096)
     .build()
 ```
 
@@ -142,5 +144,8 @@ Security-related configuration:
 
 - Keep `requireClassRegistration(true)` and register application classes or generated modules.
 - Use `withMaxDepth(...)` to reject unexpectedly deep object graphs.
+- Keep `withMaxTypeFields(...)`, `withMaxTypeMetaBytes(...)`, and the remote schema-version limits
+  at their defaults unless the data is not malicious and a trusted peer sends larger metadata or
+  many schema versions.
 - Follow [Java Configuration](../java/configuration.md#security) for allow-listing and unknown-class
   controls.
diff --git a/docs/guide/python/configuration.md b/docs/guide/python/configuration.md
index 02c61eb113..fdd6459fea 100644
--- a/docs/guide/python/configuration.md
+++ b/docs/guide/python/configuration.md
@@ -36,6 +36,10 @@ class Fory:
         strict: bool = True,
         compatible: Optional[bool] = None,
         max_depth: int = 50,
+        max_type_fields: int = 512,
+        max_type_meta_bytes: int = 4096,
+        max_schema_versions_per_type: int = 10,
+        max_average_schema_versions_per_type: int = 3,
         policy: DeserializationPolicy = None,
         field_nullable: bool = False,
         meta_compressor=None,
@@ -55,17 +59,21 @@ class ThreadSafeFory:
 
 ## Parameters
 
-| Parameter         | Type                            | Default | Description                                                                                                                                              |
-| ----------------- | ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `xlang`           | `bool`                          | `True`  | Use xlang mode. Set `False` for Python native mode.                                                                                                      |
-| `ref`             | `bool`                          | `False` | Enable reference tracking for shared/circular references. Disable for better performance if your data has no shared references.                          |
-| `strict`          | `bool`                          | `True`  | Require type registration for security. Keep this enabled for production unless a policy owns trust decisions.                                           |
-| `compatible`      | `bool \| None`                  | `None`  | Schema evolution mode. `None` enables compatible mode in both xlang and native mode. Set `False` only when every reader and writer uses the same schema. |
-| `max_depth`       | `int`                           | `50`    | Maximum deserialization depth for security, preventing stack overflow attacks.                                                                           |
-| `policy`          | `DeserializationPolicy \| None` | `None`  | Deserialization policy used for security checks. Strongly recommended when `strict=False`.                                                               |
-| `field_nullable`  | `bool`                          | `False` | Treat dataclass fields as nullable by default.                                                                                                           |
-| `meta_compressor` | `Any`                           | `None`  | Optional metadata compressor used for compatible-mode metadata encoding.                                                                                 |
-| `fory_factory`    | `Callable \| None`              | `None`  | `ThreadSafeFory` factory hook. When set, `ThreadSafeFory` creates instances via this callback; otherwise it forwards `**kwargs` to `Fory` construction.  |
+| Parameter                              | Type                            | Default | Description                                                                                                                                              |
+| -------------------------------------- | ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `xlang`                                | `bool`                          | `True`  | Use xlang mode. Set `False` for Python native mode.                                                                                                      |
+| `ref`                                  | `bool`                          | `False` | Enable reference tracking for shared/circular references. Disable for better performance if your data has no shared references.                          |
+| `strict`                               | `bool`                          | `True`  | Require type registration for security. Keep this enabled for production unless a policy owns trust decisions.                                           |
+| `compatible`                           | `bool \| None`                  | `None`  | Schema evolution mode. `None` enables compatible mode in both xlang and native mode. Set `False` only when every reader and writer uses the same schema. |
+| `max_depth`                            | `int`                           | `50`    | Maximum deserialization depth for security, preventing stack overflow attacks.                                                                           |
+| `max_type_fields`                      | `int`                           | `512`   | Maximum fields accepted in one received remote struct metadata body.                                                                                     |
+| `max_type_meta_bytes`                  | `int`                           | `4096`  | Maximum encoded body bytes accepted for one received TypeDef body, excluding the 8-byte header and any extended-size varint.                             |
+| `max_schema_versions_per_type`         | `int`                           | `10`    | Maximum accepted remote metadata versions for one logical type.                                                                                          |
+| `max_average_schema_versions_per_type` | `int`                           | `3`     | Average accepted remote metadata versions across accepted remote types. The effective global floor is `8192` schemas.                                    |
+| `policy`                               | `DeserializationPolicy \| None` | `None`  | Deserialization policy used for security checks. Strongly recommended when `strict=False`.                                                               |
+| `field_nullable`                       | `bool`                          | `False` | Treat dataclass fields as nullable by default.                                                                                                           |
+| `meta_compressor`                      | `Any`                           | `None`  | Optional metadata compressor used for compatible-mode metadata encoding.                                                                                 |
+| `fory_factory`                         | `Callable \| None`              | `None`  | `ThreadSafeFory` factory hook. When set, `ThreadSafeFory` creates instances via this callback; otherwise it forwards `**kwargs` to `Fory` construction.  |
 
 ## Key Methods
 
@@ -185,6 +193,10 @@ fory = pyfory.Fory(
     ref=False,
     strict=True,
     max_depth=50,
+    max_type_fields=512,
+    max_type_meta_bytes=4096,
+    max_schema_versions_per_type=10,
+    max_average_schema_versions_per_type=3,
 )
 
 fory.register(UserModel, name="example.User")
@@ -204,6 +216,16 @@ fory = pyfory.Fory(
 )
 ```
 
+Received remote metadata is also limited:
+
+- `max_type_fields` limits the number of fields accepted in one received struct metadata body.
+- `max_type_meta_bytes` limits the encoded body bytes accepted for one received TypeDef body.
+- `max_schema_versions_per_type` limits accepted remote metadata versions for one logical type.
+- `max_average_schema_versions_per_type` limits the average across accepted remote types.
+
+These limits do not change `strict`, `policy`, dynamic loading, unknown-class handling, or
+schema-evolution semantics.
+
 ### DeserializationPolicy
 
 When `strict=False` is necessary, use `DeserializationPolicy` to restrict the dynamic types and
diff --git a/docs/guide/rust/configuration.md b/docs/guide/rust/configuration.md
index 4d93c53056..58bd070567 100644
--- a/docs/guide/rust/configuration.md
+++ b/docs/guide/rust/configuration.md
@@ -88,6 +88,28 @@ let fory = Fory::builder().max_dyn_depth(10).build(); // Allow up to 10 levels
 
 Note: Static data types (non-dynamic types) are secure by nature and not subject to depth limits, as their structure is known at compile time.
 
+### Remote Schema Metadata Limits
+
+Compatible mode can receive remote metadata for schema evolution. These limits
+bound metadata size and accepted schema versions:
+
+```rust
+let fory = Fory::builder()
+    .max_type_fields(512)
+    .max_type_meta_bytes(4096)
+    .max_schema_versions_per_type(10)
+    .max_average_schema_versions_per_type(3)
+    .build();
+```
+
+- `max_type_fields` defaults to `512` and limits fields in one received struct metadata body.
+- `max_type_meta_bytes` defaults to `4096` and limits encoded body bytes in one received TypeDef or
+  TypeMeta body, excluding the 8-byte header and any extended-size varint.
+- `max_schema_versions_per_type` defaults to `10` and limits accepted remote metadata versions for
+  one logical type.
+- `max_average_schema_versions_per_type` defaults to `3` and limits the average across accepted
+  remote types. The effective global floor is `8192` schemas.
+
 ### Explicit Xlang Examples
 
 Set `.xlang(true)` explicitly for xlang serialization examples:
@@ -122,11 +144,15 @@ let fory = Fory::builder()
 
 ## Configuration Summary
 
-| Option               | Description                             | Default |
-| -------------------- | --------------------------------------- | ------- |
-| `compatible(bool)`   | Enable schema evolution                 | `true`  |
-| `xlang(bool)`        | Use xlang mode                          | `true`  |
-| `max_dyn_depth(u32)` | Maximum nesting depth for dynamic types | `5`     |
+| Option                                        | Description                                       | Default |
+| --------------------------------------------- | ------------------------------------------------- | ------- |
+| `compatible(bool)`                            | Enable schema evolution                           | `true`  |
+| `xlang(bool)`                                 | Use xlang mode                                    | `true`  |
+| `max_dyn_depth(u32)`                          | Maximum nesting depth for dynamic types           | `5`     |
+| `max_type_fields(usize)`                      | Max fields in one received struct metadata body   | `512`   |
+| `max_type_meta_bytes(usize)`                  | Max encoded bytes in one received metadata body   | `4096`  |
+| `max_schema_versions_per_type(usize)`         | Max remote metadata versions for one logical type | `10`    |
+| `max_average_schema_versions_per_type(usize)` | Average remote metadata versions across types     | `3`     |
 
 ## Compatible Mode
 
@@ -143,6 +169,8 @@ Security-related configuration:
 - Register application structs and trait-object implementations before deserializing untrusted
   payloads.
 - Use `max_dyn_depth(...)` to reject unexpectedly deep dynamic object graphs.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
 - Prefer concrete typed fields over `dyn Any` or broad trait-object fields for untrusted input.
 
 ## Related Topics
diff --git a/docs/guide/scala/configuration.md b/docs/guide/scala/configuration.md
index d78e648d28..397657d873 100644
--- a/docs/guide/scala/configuration.md
+++ b/docs/guide/scala/configuration.md
@@ -179,6 +179,8 @@ and any untrusted payload source:
 val fory = ForyScala.builder()
   .requireClassRegistration(true)
   .withMaxDepth(50)
+  .withMaxTypeFields(512)
+  .withMaxTypeMetaBytes(4096)
   .build()
 ```
 
@@ -186,5 +188,8 @@ Security-related configuration:
 
 - Keep `requireClassRegistration(true)` and register application classes or generated modules.
 - Use `withMaxDepth(...)` to reject unexpectedly deep object graphs.
+- Keep `withMaxTypeFields(...)`, `withMaxTypeMetaBytes(...)`, and the remote schema-version limits
+  at their defaults unless the data is not malicious and a trusted peer sends larger metadata or
+  many schema versions.
 - Follow [Java Configuration](../java/configuration.md#security) for allow-listing and unknown-class
   controls.
diff --git a/docs/guide/swift/configuration.md b/docs/guide/swift/configuration.md
index 85c1e33257..e3a0478817 100644
--- a/docs/guide/swift/configuration.md
+++ b/docs/guide/swift/configuration.md
@@ -31,6 +31,10 @@ public struct Config {
   public let compatible: Bool
   public let checkClassVersion: Bool
   public let maxDepth: Int
+  public let maxTypeFields: Int
+  public let maxTypeMetaBytes: Int
+  public let maxSchemaVersionsPerType: Int
+  public let maxAverageSchemaVersionsPerType: Int
 }
 ```
 
@@ -86,10 +90,25 @@ let fory = Fory(compatible: false, checkClassVersion: true)
 
 ### Size and Depth Limits
 
-`maxDepth` bounds decoded payload nesting depth.
+`maxDepth` bounds decoded payload nesting depth. Compatible-mode remote metadata
+is also limited:
+
+- `maxTypeFields` defaults to `512` and limits fields in one received struct metadata body.
+- `maxTypeMetaBytes` defaults to `4096` and limits encoded body bytes in one received TypeMeta body,
+  excluding the 8-byte header and any extended-size varint.
+- `maxSchemaVersionsPerType` defaults to `10` and limits accepted remote metadata versions for one
+  logical type.
+- `maxAverageSchemaVersionsPerType` defaults to `3` and limits the average across accepted remote
+  types. The effective global floor is `8192` schemas.
 
 ```swift
-let fory = Fory(maxDepth: 5)
+let fory = Fory(
+  maxDepth: 5,
+  maxTypeFields: 512,
+  maxTypeMetaBytes: 4096,
+  maxSchemaVersionsPerType: 10,
+  maxAverageSchemaVersionsPerType: 3
+)
 ```
 
 ## Recommended Presets
@@ -121,3 +140,5 @@ Security-related configuration:
 - Register only the expected generated models before deserializing untrusted payloads.
 - Use `checkClassVersion` with `compatible: false` for intentional same-schema payloads.
 - Set `maxDepth` for the largest nesting depth your service accepts.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+  trusted peer sends larger metadata or many schema versions.
diff --git a/docs/guide/xlang/serialization.md b/docs/guide/xlang/serialization.md
index 338f58fcb6..cdf136a353 100644
--- a/docs/guide/xlang/serialization.md
+++ b/docs/guide/xlang/serialization.md
@@ -23,6 +23,41 @@ This page demonstrates common cross-language serialization patterns. Data serial
 supported language can be deserialized in any other supported language when peers use matching type
 identity, field schema, and compatibility settings.
 
+## Remote Schema Metadata Limits
+
+Compatible mode may receive remote metadata (`TypeDef` or `TypeMeta`) for types that are not already
+known by the reader. Fory limits how many distinct remote metadata versions can be accepted, and
+also limits the size of each received metadata body:
+
+- `maxSchemaVersionsPerType`: maximum accepted remote metadata versions for one logical type. The
+  default is `10`.
+- `maxAverageSchemaVersionsPerType`: average accepted remote metadata versions across all accepted
+  remote types. The default is `3`; the effective global floor is `8192` metadata entries.
+- `maxTypeFields`: maximum fields declared by one received struct metadata body. The default is
+  `512`.
+- `maxTypeMetaBytes`: maximum encoded metadata body bytes for one received TypeDef or TypeMeta body,
+  excluding the 8-byte header and any extended-size varint. The default is `4096`.
+
+These limits are resource protections. They do not change wire format, registration requirements,
+dynamic type loading, unknown-type handling, or schema-evolution compatibility.
+
+Raise these values only when the data is not malicious and a trusted peer sends larger metadata or
+many schema versions.
+
+| Language              | Field-count option  | Metadata-bytes option  | Per-type option                | Average option                         |
+| --------------------- | ------------------- | ---------------------- | ------------------------------ | -------------------------------------- |
+| Java                  | `withMaxTypeFields` | `withMaxTypeMetaBytes` | `withMaxSchemaVersionsPerType` | `withMaxAverageSchemaVersionsPerType`  |
+| Scala                 | `withMaxTypeFields` | `withMaxTypeMetaBytes` | `withMaxSchemaVersionsPerType` | `withMaxAverageSchemaVersionsPerType`  |
+| Kotlin                | `withMaxTypeFields` | `withMaxTypeMetaBytes` | `withMaxSchemaVersionsPerType` | `withMaxAverageSchemaVersionsPerType`  |
+| Python                | `max_type_fields`   | `max_type_meta_bytes`  | `max_schema_versions_per_type` | `max_average_schema_versions_per_type` |
+| JavaScript/TypeScript | `maxTypeFields`     | `maxTypeMetaBytes`     | `maxSchemaVersionsPerType`     | `maxAverageSchemaVersionsPerType`      |
+| C++                   | `max_type_fields`   | `max_type_meta_bytes`  | `max_schema_versions_per_type` | `max_average_schema_versions_per_type` |
+| Go                    | `WithMaxTypeFields` | `WithMaxTypeMetaBytes` | `WithMaxSchemaVersionsPerType` | `WithMaxAverageSchemaVersionsPerType`  |
+| Rust                  | `max_type_fields`   | `max_type_meta_bytes`  | `max_schema_versions_per_type` | `max_average_schema_versions_per_type` |
+| C#                    | `MaxTypeFields`     | `MaxTypeMetaBytes`     | `MaxSchemaVersionsPerType`     | `MaxAverageSchemaVersionsPerType`      |
+| Swift                 | `maxTypeFields`     | `maxTypeMetaBytes`     | `maxSchemaVersionsPerType`     | `maxAverageSchemaVersionsPerType`      |
+| Dart                  | `maxTypeFields`     | `maxTypeMetaBytes`     | `maxSchemaVersionsPerType`     | `maxAverageSchemaVersionsPerType`      |
+
 ## Serialize Built-in Types
 
 Common types can be serialized automatically without registration: primitive numeric types, string, binary, array, list, map, and more.


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fory.apache.org
For additional commands, e-mail: commits-help@fory.apache.org