skip infinite loop in http parsing

This commit is contained in:
Patricio Whittingslow
2026-01-01 12:21:58 -03:00
parent c6e88b1c3b
commit 5731a378dd
2 changed files with 41 additions and 25 deletions
+10 -6
View File
@@ -98,6 +98,12 @@ func (hb *headerBuf) offBuf() []byte {
return hb.buf[hb.off:] return hb.buf[hb.off:]
} }
func (hb *headerBuf) skipLeadingCRLF() {
for hb.off < len(hb.buf) && (hb.buf[hb.off] == '\n' || hb.buf[hb.off] == '\r') {
hb.off++
}
}
func (hb *headerBuf) scanLine() []byte { func (hb *headerBuf) scanLine() []byte {
buf := hb.scanUntilByte('\n') buf := hb.scanUntilByte('\n')
if len(buf) > 0 && buf[len(buf)-1] == '\r' { if len(buf) > 0 && buf[len(buf)-1] == '\r' {
@@ -122,9 +128,8 @@ func (hb *headerBuf) scanUntilByte(c byte) []byte {
func (hb *headerBuf) parseFirstLineRequest(initFlags flags) (method, uri, proto headerSlice, flags flags, err error) { func (hb *headerBuf) parseFirstLineRequest(initFlags flags) (method, uri, proto headerSlice, flags flags, err error) {
hb.off = 0 // Parsing first line resets offset. hb.off = 0 // Parsing first line resets offset.
var b []byte var b []byte
for len(b) == 0 { hb.skipLeadingCRLF()
b = hb.scanLine() b = hb.scanLine()
}
flags = initFlags flags = initFlags
if len(b) < 5 { if len(b) < 5 {
return method, uri, proto, flags, errNeedMore return method, uri, proto, flags, errNeedMore
@@ -154,9 +159,8 @@ func (hb *headerBuf) parseFirstLineRequest(initFlags flags) (method, uri, proto
func (hb *headerBuf) parseFirstLineResponse(initFlags flags) (statusCode, statusText headerSlice, flags flags, err error) { func (hb *headerBuf) parseFirstLineResponse(initFlags flags) (statusCode, statusText headerSlice, flags flags, err error) {
hb.off = 0 // Parsing first line resets offset. hb.off = 0 // Parsing first line resets offset.
var b []byte var b []byte
for len(b) == 0 { hb.skipLeadingCRLF()
b = hb.scanLine() b = hb.scanLine()
}
flags = initFlags flags = initFlags
if len(b) < 5 { if len(b) < 5 {
return statusCode, statusText, flags, errNeedMore return statusCode, statusText, flags, errNeedMore
+31 -19
View File
@@ -28,28 +28,40 @@ func TestStackAsyncTCP_multipacket(t *testing.T) {
tst := testerFrom(t, MTU) tst := testerFrom(t, MTU)
rng := rand.New(rand.NewSource(seed)) rng := rand.New(rand.NewSource(seed))
client2, sv2, clconn2, svconn2 := newTCPStacks(t, seed, MTU) client2, sv2, clconn2, svconn2 := newTCPStacks(t, seed, MTU)
_, _, _, _ = client2, sv2, clconn2, svconn2
tst.TestTCPSetupAndEstablish(sv, client, svconn, clconn, svPort, 1337) for _, clientCloses := range []bool{true, false} {
tst.TestTCPClose(client, sv, clconn, svconn) testClose := func() {
var buf [MTU]byte t.Helper()
for i := 0; i < 1; i++ { if clientCloses {
payloadSize := rng.Intn(maxPktLen) + 1 tst.TestTCPClose(client, sv, clconn, svconn)
} else {
tst.TestTCPClose(sv, client, svconn, clconn)
}
}
tst.TestTCPSetupAndEstablish(sv, client, svconn, clconn, svPort, 1337) tst.TestTCPSetupAndEstablish(sv, client, svconn, clconn, svPort, 1337)
// npkt := rng.Intn(maxNPkt-1) + 2 testClose()
a, _ := rng.Read(buf[:payloadSize]) var buf [MTU]byte
tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a]) for i := 0; i < 20; i++ {
a, _ = rng.Read(buf[:payloadSize]) payloadSize := rng.Intn(maxPktLen) + 1
tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a]) tst.TestTCPSetupAndEstablish(sv, client, svconn, clconn, svPort, 1337)
// for ipkt := 0; ipkt < npkt; ipkt++ { // npkt := rng.Intn(maxNPkt-1) + 2
// a, _ := rng.Read(buf[:payloadSize]) a, _ := rng.Read(buf[:payloadSize])
// tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a]) tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a])
// } a, _ = rng.Read(buf[:payloadSize])
tst.TestTCPClose(client, sv, clconn, svconn) tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a])
if t.Failed() { // for ipkt := 0; ipkt < npkt; ipkt++ {
t.Error("multi failed") // a, _ := rng.Read(buf[:payloadSize])
t.FailNow() // tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a])
// }
testClose()
if t.Failed() {
t.Error("multi failed")
t.FailNow()
}
} }
} }
_, _, _, _ = client2, sv2, clconn2, svconn2
} }
func TestStackAsyncTCP_singlepacket(t *testing.T) { func TestStackAsyncTCP_singlepacket(t *testing.T) {