From 1b6636afe6d689c47f751524b75ebc9e0410644e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=97=A5=E6=A2=A6=E4=B8=BB=E4=B9=89?= <37233261+Cherrling@users.noreply.github.com> Date: Sun, 19 Apr 2026 02:33:00 +0800 Subject: [PATCH] fix: repair the oom problem when enable sniff (#1547) --- extras/sniff/internal/quic/payload.go | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/extras/sniff/internal/quic/payload.go b/extras/sniff/internal/quic/payload.go index 453b714..14e80c3 100644 --- a/extras/sniff/internal/quic/payload.go +++ b/extras/sniff/internal/quic/payload.go @@ -6,12 +6,18 @@ import ( "errors" "fmt" "io" + "math" "sort" "github.com/apernet/quic-go/quicvarint" "golang.org/x/crypto/hkdf" ) +const ( + maxCryptoFrameDataLen = 256 * 1024 // 256 KiB + maxCryptoPayloadLen = 256 * 1024 // 256 KiB +) + func ReadCryptoPayload(packet []byte) ([]byte, error) { hdr, offset, err := ParseInitialHeader(packet) if err != nil { @@ -82,11 +88,20 @@ func extractCryptoFrames(r *bytes.Reader) ([]cryptoFrame, error) { if err != nil { return nil, err } + if offset > uint64(math.MaxInt64) { + return nil, errors.New("invalid crypto frame offset") + } frame.Offset = int64(offset) dataLen, err := quicvarint.Read(r) if err != nil { return nil, err } + if dataLen > maxCryptoFrameDataLen { + return nil, errors.New("crypto frame data too large") + } + if dataLen > uint64(r.Len()) { + return nil, io.ErrUnexpectedEOF + } frame.Data = make([]byte, dataLen) if _, err := io.ReadFull(r, frame.Data); err != nil { return nil, err @@ -114,7 +129,18 @@ func assembleCryptoFrames(frames []cryptoFrame) []byte { } } // concatenate the frames - data := make([]byte, frames[len(frames)-1].Offset+int64(len(frames[len(frames)-1].Data))) + last := frames[len(frames)-1] + if last.Offset < 0 { + return nil + } + if last.Offset > maxCryptoPayloadLen { + return nil + } + end := last.Offset + int64(len(last.Data)) + if end < 0 || end > maxCryptoPayloadLen { + return nil + } + data := make([]byte, end) for _, frame := range frames { copy(data[frame.Offset:], frame.Data) }