From fa8bef8688272294680dcc39f714d0a53fb4186b Mon Sep 17 00:00:00 2001 From: 36huo Date: Mon, 11 May 2026 18:02:41 +0800 Subject: [PATCH] fix(v3): fix strict mode TLS 1.3 detection bug - v3_server.go: isServerHelloSupportTLS13 treated extensionListLength as number of extensions instead of total byte length, causing out-of-bounds reads - v3_client.go: isServerHelloSupportTLS13 was called with buffer[5:] (already stripped TLS record header), but the function expected the full frame including header, causing parsing offset error Fixes: strict mode always fails with TLS 1.3 servers --- v3_client.go | 2 +- v3_server.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/v3_client.go b/v3_client.go index 2a914ed..911e5c9 100644 --- a/v3_client.go +++ b/v3_client.go @@ -85,7 +85,7 @@ func (w *streamWrapper) Read(p []byte) (n int, err error) { w.readHMAC = hmac.New(sha1.New, []byte(w.password)) w.readHMAC.Write(w.serverRandom) w.readHMACKey = kdf(w.password, w.serverRandom) - w.isTLS13 = isServerHelloSupportTLS13(buffer[5:]) + w.isTLS13 = isServerHelloSupportTLS13(buffer) if !w.isTLS13 { w.authorized = true } diff --git a/v3_server.go b/v3_server.go index eebd3ef..f4ad4c5 100644 --- a/v3_server.go +++ b/v3_server.go @@ -110,7 +110,10 @@ func isServerHelloSupportTLS13(frame []byte) bool { if err != nil { return false } - for i := uint16(0); i < extensionListLength; i++ { + // extensionListLength is the total byte length of all extensions, + // NOT the number of extensions. Iterate by bytes consumed. + extensionsRead := uint16(0) + for extensionsRead < extensionListLength { var extensionType uint16 err = binary.Read(reader, binary.BigEndian, &extensionType) if err != nil { @@ -121,6 +124,7 @@ func isServerHelloSupportTLS13(frame []byte) bool { if err != nil { return false } + extensionsRead += 4 + extensionLength if extensionType != 43 { _, err = io.CopyN(io.Discard, reader, int64(extensionLength)) if err != nil {