nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: quic-go/quic-go
Pull request #4878 (2025-01-15 13:15:36)

reject NEW_CONNECTION_ID frames when using zero-length connection IDs
The RFC says:
> An endpoint that selects a zero-length connection ID during the handshake cannot issue a new connection ID. A zero-length Destination Connection ID field is used in all packets sent toward such an endpoint over any network path.

marten-seemann: Thanks for checking @mxinden!

Patch:
diff --git a/conn_id_manager.go b/conn_id_manager.go
index 4aa3f749..0e65231c 100644
--- a/conn_id_manager.go
+++ b/conn_id_manager.go
@@ -66,6 +66,12 @@ func (h *connIDManager) Add(f *wire.NewConnectionIDFrame) error {
 }
 
 func (h *connIDManager) add(f *wire.NewConnectionIDFrame) error {
+	if h.activeConnectionID.Len() == 0 {
+		return &qerr.TransportError{
+			ErrorCode:    qerr.ProtocolViolation,
+			ErrorMessage: "received NEW_CONNECTION_ID frame but zero-length connection IDs are in use",
+		}
+	}
 	// If the NEW_CONNECTION_ID frame is reordered, such that its sequence number is smaller than the currently active
 	// connection ID or if it was already retired, send the RETIRE_CONNECTION_ID frame immediately.
 	if f.SequenceNumber < h.activeSequenceNumber || f.SequenceNumber < h.highestRetired {


Test patch:
diff --git a/conn_id_manager_test.go b/conn_id_manager_test.go
index ffe435de..193d74c2 100644
--- a/conn_id_manager_test.go
+++ b/conn_id_manager_test.go
@@ -209,6 +209,26 @@ func TestConnIDManagerConnIDRotation(t *testing.T) {
 	require.Equal(t, []wire.Frame{&wire.RetireConnectionIDFrame{SequenceNumber: 2}}, frameQueue)
 }
 
+func TestConnIDManagerZeroLengthConnectionID(t *testing.T) {
+	m := newConnIDManager(
+		protocol.ConnectionID{},
+		func(protocol.StatelessResetToken) {},
+		func(protocol.StatelessResetToken) {},
+		func(f wire.Frame) {},
+	)
+	require.Equal(t, protocol.ConnectionID{}, m.Get())
+	for i := 0; i < 5*protocol.PacketsPerConnectionID; i++ {
+		m.SentPacket()
+		require.Equal(t, protocol.ConnectionID{}, m.Get())
+	}
+
+	require.ErrorIs(t, m.Add(&wire.NewConnectionIDFrame{
+		SequenceNumber:      1,
+		ConnectionID:        protocol.ConnectionID{},
+		StatelessResetToken: protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
+	}), &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
+}
+
 func TestConnIDManagerClose(t *testing.T) {
 	var addedTokens, removedTokens []protocol.StatelessResetToken
 	m := newConnIDManager(
Repository: quic-go/quic-go
Pull request #4971 (2025-02-24 12:41:29)

trace drop of unknown-version packets when Version Negotiation is off
Discovered when working on #4969.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/4971?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 84.07%. Comparing base [(`751ca8d`)](https://app.codecov.io/gh/quic-go/quic-go/commit/751ca8dfb6de8455b27296ce4ff57ca87d9ca914?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`93ac25f`)](https://app.codecov.io/gh/quic-go/quic-go/commit/93ac25f8b478c33022d070adbe360add0684dd60?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4971      +/-   ##
==========================================
- Coverage   84.19%   84.07%   -0.12%     
==========================================
  Files         152      149       -3     
  Lines       16618    16274     -344     
==========================================
- Hits        13991    13682     -309     
+ Misses       2101     2081      -20     
+ Partials      526      511      -15     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/4971?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


Patch:
diff --git a/server.go b/server.go
index 2bb821ab..092521b9 100644
--- a/server.go
+++ b/server.go
@@ -426,6 +426,9 @@ func (s *baseServer) handlePacketImpl(p receivedPacket) bool /* is the buffer st
 	// send a Version Negotiation Packet if the client is speaking a different protocol version
 	if !protocol.IsSupportedVersion(s.config.Versions, v) {
 		if s.disableVersionNegotiation {
+			if s.tracer != nil && s.tracer.DroppedPacket != nil {
+				s.tracer.DroppedPacket(p.remoteAddr, logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropUnexpectedVersion)
+			}
 			return false
 		}
 


Test patch:
diff --git a/server_test.go b/server_test.go
index 64a16c51..5d3535d9 100644
--- a/server_test.go
+++ b/server_test.go
@@ -385,6 +385,7 @@ var _ = Describe("Server", func() {
 				raddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
 				packet.remoteAddr = raddr
 				done := make(chan struct{})
+				tracer.EXPECT().DroppedPacket(raddr, logging.PacketTypeNotDetermined, packet.Size(), logging.PacketDropUnexpectedVersion)
 				serv.handlePacket(packet)
 				Consistently(done, 50*time.Millisecond).ShouldNot(BeClosed())
 			})
Repository: quic-go/quic-go
Pull request #5095 (2025-04-29 09:46:21)

http3: return http.ErrServerClosed for ServeQUICConn after Server.Close
I discovered this when working on #5085.


Patch:
diff --git a/http3/server.go b/http3/server.go
index 3353f0af..6773a96c 100644
--- a/http3/server.go
+++ b/http3/server.go
@@ -264,6 +264,11 @@ func (s *Server) decreaseConnCount() {
 // ServeQUICConn serves a single QUIC connection.
 func (s *Server) ServeQUICConn(conn quic.Connection) error {
 	s.mutex.Lock()
+	if s.closed {
+		s.mutex.Unlock()
+		return http.ErrServerClosed
+	}
+
 	s.init()
 	s.mutex.Unlock()
 


Test patch:
diff --git a/http3/server_test.go b/http3/server_test.go
index 3f6f29a3..43dfc168 100644
--- a/http3/server_test.go
+++ b/http3/server_test.go
@@ -883,6 +883,7 @@ var _ = Describe("Server", func() {
 		serv := &Server{}
 		Expect(serv.Close()).To(Succeed())
 		Expect(serv.ListenAndServeTLS(testdata.GetCertificatePaths())).To(MatchError(http.ErrServerClosed))
+		Expect(serv.ServeQUICConn(nil)).To(MatchError(http.ErrServerClosed))
 	})
 
 	It("handles concurrent Serve and Close", func() {
Repository: quic-go/quic-go
Pull request #5136 (2025-05-10 12:04:02)

http3: keep datagram receive loop running on datagram for unknown stream
#5133 contains the test.


Patch:
diff --git a/http3/conn.go b/http3/conn.go
index 1a9a410e..cbbe4445 100644
--- a/http3/conn.go
+++ b/http3/conn.go
@@ -308,11 +308,10 @@ func (c *connection) receiveDatagrams() error {
 		streamID := protocol.StreamID(4 * quarterStreamID)
 		c.streamMx.Lock()
 		dg, ok := c.streams[streamID]
+		c.streamMx.Unlock()
 		if !ok {
-			c.streamMx.Unlock()
-			return nil
+			continue
 		}
-		c.streamMx.Unlock()
 		dg.enqueue(b[n:])
 	}
 }


Test patch:
diff --git a/http3/conn_test.go b/http3/conn_test.go
index 7eb33840..d97508de 100644
--- a/http3/conn_test.go
+++ b/http3/conn_test.go
@@ -392,6 +392,7 @@ var _ = Describe("Connection", func() {
 				close(delivered)
 				return b, nil
 			})
+			qconn.EXPECT().ReceiveDatagram(gomock.Any()).Return(nil, errors.New("test done"))
 			go func() {
 				defer GinkgoRecover()
 				conn.handleUnidirectionalStreams(nil)