aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2025-09-30 15:11:16 -0700
committerGopher Robot <gobot@golang.org>2025-10-07 11:00:38 -0700
commita402f4ad285514f5f3db90516d72047d591b307a (patch)
tree12ce5f8f46b3fd99b6e594f5b3f77186f95325a8
parentf9f198ab05e3282cbf6b13251d47d9141981e401 (diff)
downloadgo-a402f4ad285514f5f3db90516d72047d591b307a.tar.xz
[release-branch.go1.24] net/textproto: avoid quadratic complexity in Reader.ReadResponse
Reader.ReadResponse constructed a response string from repeated string concatenation, permitting a malicious sender to cause excessive memory allocation and CPU consumption by sending a response consisting of many short lines. Use a strings.Builder to construct the string instead. Thanks to Jakub Ciolek for reporting this issue. Fixes CVE-2025-61724 For #75716 Fixes #75717 Change-Id: I1a98ce85a21b830cb25799f9ac9333a67400d736 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2940 Reviewed-by: Roland Shoemaker <bracewell@google.com> Reviewed-by: Nicholas Husin <husin@google.com> Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2980 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/709837 Reviewed-by: Carlos Amedee <carlos@golang.org> TryBot-Bypass: Michael Pratt <mpratt@google.com> Auto-Submit: Michael Pratt <mpratt@google.com>
-rw-r--r--src/net/textproto/reader.go11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index f98e05bd1d..2c926ca876 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -284,8 +284,10 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
//
// An expectCode <= 0 disables the check of the status code.
func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
- code, continued, message, err := r.readCodeLine(expectCode)
+ code, continued, first, err := r.readCodeLine(expectCode)
multi := continued
+ var messageBuilder strings.Builder
+ messageBuilder.WriteString(first)
for continued {
line, err := r.ReadLine()
if err != nil {
@@ -296,12 +298,15 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
var moreMessage string
code2, continued, moreMessage, err = parseCodeLine(line, 0)
if err != nil || code2 != code {
- message += "\n" + strings.TrimRight(line, "\r\n")
+ messageBuilder.WriteByte('\n')
+ messageBuilder.WriteString(strings.TrimRight(line, "\r\n"))
continued = true
continue
}
- message += "\n" + moreMessage
+ messageBuilder.WriteByte('\n')
+ messageBuilder.WriteString(moreMessage)
}
+ message = messageBuilder.String()
if err != nil && multi && message != "" {
// replace one line error message with all lines (full message)
err = &Error{code, message}