From a402f4ad285514f5f3db90516d72047d591b307a Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Tue, 30 Sep 2025 15:11:16 -0700
Subject: [PATCH] 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>

CVE: CVE-2025-61724

Upstream-Status: Backport [https://github.com/golang/go/commit/a402f4ad285514f5f3db90516d72047d591b307a]

Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
---
 src/net/textproto/reader.go | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index 3ac4d4d..a996257 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -288,8 +288,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 {
@@ -300,12 +302,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}
-- 
2.40.0

