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.git
The following commit(s) were added to refs/heads/main by this push:
new 62b0d91fc fix(go): added maxBinarySize limit to decimal
deserialization (#3623)
62b0d91fc is described below
commit 62b0d91fc1bea1a34c15e3416c0b1f0bc7540437
Author: Ayush Kumar <[email protected]>
AuthorDate: Mon Apr 27 15:24:16 2026 +0530
fix(go): added maxBinarySize limit to decimal deserialization (#3623)
## Why?
the deserialization of arbitrary-precision DECIMAL numbers involves
reading a magnitude payload byte array. The length of this payload is
derived from the header's metadata and is completely
attacker-controlled.
## What does this PR do?
use `ctx.ReadBinaryLength()` which correctly enforces `maxBinarySize`
guardrails.
## Related issues
## AI Contribution Checklist
- [ ] Substantial AI assistance was used in this PR: `yes` / `no`
- [ ] If `yes`, I included a completed [AI Contribution
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
in this PR description and the required `AI Usage Disclosure`.
- [ ] If `yes`, my PR description includes the required `ai_review`
summary and screenshot evidence of the final clean AI review results
from both fresh reviewers on the current PR diff or current HEAD after
the latest code changes.
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
go/fory/decimal.go | 6 +++++-
go/fory/decimal_test.go | 24 ++++++++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/go/fory/decimal.go b/go/fory/decimal.go
index d7acd27c9..92d6e15be 100644
--- a/go/fory/decimal.go
+++ b/go/fory/decimal.go
@@ -134,10 +134,14 @@ func readDecimalParts(ctx *ReadContext) (int32, *big.Int)
{
meta := header >> 1
length := meta >> 1
- if length == 0 || length > uint64(MaxInt32) {
+ if length == 0 {
ctx.SetError(DeserializationErrorf("invalid decimal magnitude
length %d", length))
return 0, nil
}
+ if length > uint64(ctx.maxBinarySize) {
+ ctx.SetError(MaxBinarySizeExceededError(int(length),
ctx.maxBinarySize))
+ return 0, nil
+ }
payload := ctx.buffer.ReadBytes(int(length), err)
if ctx.HasError() {
return 0, nil
diff --git a/go/fory/decimal_test.go b/go/fory/decimal_test.go
index 0acd9fbcc..a54e7907d 100644
--- a/go/fory/decimal_test.go
+++ b/go/fory/decimal_test.go
@@ -18,6 +18,7 @@
package fory
import (
+ "bytes"
"math/big"
"testing"
@@ -131,3 +132,26 @@ func TestDecimalRejectsNonCanonicalBigPayload(t
*testing.T) {
require.Error(t, err)
require.Contains(t, err.Error(), "trailing zero byte")
}
+
+func TestDecimalOOM(t *testing.T) {
+ maliciousLength := uint64(2000000000)
+
+ buffer := NewByteBuffer(nil)
+ buffer.WriteByte_(XLangFlag)
+ buffer.WriteInt8(NotNullValueFlag)
+ buffer.WriteUint8(uint8(DECIMAL))
+ buffer.WriteVarint32(0)
+
+ meta := (maliciousLength << 1) | 0
+ header := (meta << 1) | 1
+ buffer.WriteVarUint64(header)
+
+ data := buffer.Bytes()
+
+ f := New(WithXlang(true), WithMaxBinarySize(1024*1024))
+
+ var decoded Decimal
+ err := f.DeserializeFromReader(bytes.NewReader(data), &decoded)
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "max binary size exceeded")
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]