#4759·gin

BSON 和 Protobuf 绑定会读取整个请求体,不受大小限制

作者: GG-Feng创建于 2026年7月25日更新于 2026年8月6日
标签type/bug

说明

□ 总结

BSON和Protobuf绑定器在解析前将整个请求体读入内存.

如果应用程序使用这些绑定器时没有应用程序级别或代理级别的机身尺寸限制,一个大型请求机体可以强制服务器侧内存大分配并导致资源耗尽.

□ 受影响的代码

文件:`装订/bson.go'

开始 func (b bsonBinding) (中文(简体) ). 请求, obj any) 错误{ buf, 错误 := io. Readall( req.Body) 如果错误===== 错误=b. BindBody(buf,obj) {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢? 返回错误 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢?


文件:`装订/protobuf.go'

开始
func (b protobufBinding) Bind(req *http.). 请求, obj any) 错误{
buf, 错误 := io. Readall( req.Body)
如果错误 ! = 无 {
返回错误
{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢?
b. BindBody (buf, obj) 返回状态
{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢?

两条路径都叫"io.Readall(req. `不应用最大尺寸。

□再现.

我重现了针对一个最小的金币服务器的行为,它直接称为真正的"约束". 布莱恩。 带路。

一个小请求机构只导致少量拨款:

页:1 装订。 布莱恩。 绑定错误=无效文档长度 平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平面平


一个200 MB 请求正文导致请求正文在解析失败前被完全读入内存 :

页:1
装订。 布莱恩。 绑定错误=无效文档长度
HeapAlloc=516.6 MiB 总Alloc=516.8 MiB(德尔塔与基线=+516.2 MiB)

剖析出的错误发生在全身已经被读取后,所以即使身体无效,内存消耗也会被触发.

Protobuf 绑定器使用相同的"io.Readall(req.)". (b) 模式。

□ 预期行为

Binders应该避免无约束的请求被读取,或者Gin应该提供一种明确的内在方式来强制实施这些绑取物的最大体积.

□ 实际行为

BSON和Protobuf绑定器将完整的请求体读入内存而无大小限制.

□ 影响

一个客户端可以使用这些绑定器将一个非常大的请求正文发送到一个端点并强制进行大量的内存分配. 如果不设定外部请求的大小限制,这可能导致资源枯竭或服务退化。

□ 建议修补

  • 为需要缓冲整个请求体的绑定器增加可配置的最大体积。
  • 在拨打`io'之前,先使用一个定界读取器。 全读.
  • 记录默认行为 使用 BSON 或 Protobuf 约束的应用程序知道它们必须执行请求大小限制 。

QQ 银版

人参/人参@34dac20

你能复制虫子吗?

QQ 源代码

开始 主软件包

导入( E) "fmt" (英语). "网/http" (中文(简体) ). "运行时间"

"GitHub.com/gin-gonic/gin" 互联网档案馆的存檔,存档日期2013-12-02. "GitHub.com/gin-gonic/gin/binding" (中文(简体) ). (中文(简体) ).

func 主 () { r:= 杜松子酒. Default () (中文(简体) ).

r.POST (""/bson"), func (c *gin.context) { var before, 运行时间之后。 示意图 运行时间。 读取MemStats( & before)

有吗? 错误:=绑定. BSON. 宾德( c. 请求, & obj)

运行时间。 读取MemStats( & 之后)

c. String(http. 状态OK, "bonding.BSON.Bind mrow\v\nHeapAlloc\lf MiB TotalAlloc\lif MiB\n","BSON. 错 . . . . . . .