From 732d76f7a07f5267d5f504913f2c963eaaf9acee Mon Sep 17 00:00:00 2001 From: Daniel Linsley Date: Wed, 28 Oct 2026 16:09:01 -0700 Subject: [PATCH] Fix syslog server panic on RFC5424 nil timestamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC5424 §6.2.3 allows the TIMESTAMP field to be the NILVALUE "-", in which case the parser leaves msg.Timestamp nil. convertToEnvelope dereferenced it unconditionally, so a single such message panicked the syslog server. - Fall back to the time of receipt when the timestamp is nil. - Return early in parseListener when the result is not an RFC5424 message; previously it logged the error and fell through. - Add a test that a nil-timestamp message is accepted and stamped with the receive time. --- src/internal/syslog/server.go | 12 +++++++++++- src/internal/syslog/server_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/internal/syslog/server.go b/src/internal/syslog/server.go index b4b21a5c..8659758d 100644 --- a/src/internal/syslog/server.go +++ b/src/internal/syslog/server.go @@ -203,6 +203,7 @@ func (s *Server) parseListener(res *syslog.Result) { if !ok { s.invalidIngress.Add(1) s.loggr.Printf("invalid message format: not rfc5424") + return } env, err := s.convertToEnvelope(msg) @@ -229,9 +230,18 @@ func (s *Server) convertToEnvelope(msg *rfc5424.SyslogMessage) (*loggregator_v2. return nil, fmt.Errorf("missing app name in syslog message") } + var timestamp int64 + if msg.Timestamp != nil { + timestamp = msg.Timestamp.UnixNano() + } else { + // RFC5424 §6.2.3 allows the TIMESTAMP to be the NILVALUE "-", in which + // case the parser leaves it nil. Fall back to the time of receipt. + timestamp = time.Now().UnixNano() + } + env := &loggregator_v2.Envelope{ SourceId: *sourceID, - Timestamp: msg.Timestamp.UnixNano(), + Timestamp: timestamp, InstanceId: instanceId, Tags: map[string]string{}, } diff --git a/src/internal/syslog/server_test.go b/src/internal/syslog/server_test.go index ab901440..13e046b4 100644 --- a/src/internal/syslog/server_test.go +++ b/src/internal/syslog/server_test.go @@ -117,6 +117,31 @@ var _ = Describe("Server", func() { }).Should(Equal(5.0)) }) + // RFC5424 allows the TIMESTAMP to be the NILVALUE "-", which leaves + // msg.Timestamp nil. The server must accept it and use the receive time. + It("accepts a message with a nil timestamp", func() { + before := time.Now() + body := `<14>1 - test-hostname test-app-id [APP/2] - - just a test` + _, err := fmt.Fprintf(clientConn, "%d %s", len(body), body) + Expect(err).ToNot(HaveOccurred()) + + Expect(server.Stream(context.Background(), &loggregator_v2.EgressBatchRequest{})()).Should(ContainElement( + SatisfyAll( + HaveField("SourceId", "test-app-id"), + HaveField("InstanceId", "2"), + HaveField("Timestamp", BeNumerically(">=", before.UnixNano())), + HaveField("Timestamp", BeNumerically("<=", time.Now().UnixNano())), + HaveField("Message", &loggregator_v2.Envelope_Log{ + Log: &loggregator_v2.Log{ + Payload: []byte("just a test"), + Type: loggregator_v2.Log_OUT, + }, + }), + ), + )) + Expect(spyRegistry.GetMetric("invalid_ingress", nil).Value()).To(Equal(0.0)) + }) + DescribeTable("message streaming", func(msg string, expected *loggregator_v2.Envelope) { _, err := fmt.Fprint(clientConn, msg)