From 54b17b0700dc7f8e756d06e0123e03cad08d252a Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Thu, 24 Apr 2025 23:37:48 -0400 Subject: [PATCH] improve robustness of timestamp parsing (#2250) * Clamp CHATHISTORY timestamp selectors to be in [0, MaxInt64] * Convert everything to UTC up front (probably a no-op) --- irc/handlers.go | 9 +++++++++ irc/server.go | 3 +++ 2 files changed, 12 insertions(+) diff --git a/irc/handlers.go b/irc/handlers.go index 2256af79..d0d619c0 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -755,6 +755,14 @@ func chathistoryHandler(server *Server, client *Client, msg ircmsg.Message, rb * return } else if identifier == "timestamp" { timestamp, err = time.Parse(IRCv3TimestampFormat, value) + if err == nil { + timestamp = timestamp.UTC() + if timestamp.Before(unixEpoch) { + timestamp = unixEpoch + } else if timestamp.After(year2262Problem) { + timestamp = year2262Problem + } + } return } return @@ -3052,6 +3060,7 @@ func markReadHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res rb.Add(nil, server.name, "FAIL", "MARKREAD", "INVALID_PARAMS", utils.SafeErrorParam(readTimestamp), client.t("Invalid timestamp")) return } + readTime = readTime.UTC() result := client.SetReadMarker(cftarget, readTime) readTimestamp = fmt.Sprintf("timestamp=%s", result.Format(IRCv3TimestampFormat)) // inform the originating session whether it was a success or a no-op: diff --git a/irc/server.go b/irc/server.go index aefeb00d..88203e50 100644 --- a/irc/server.go +++ b/irc/server.go @@ -65,6 +65,9 @@ var ( throttleMessage = "You have attempted to connect too many times within a short duration. Wait a while, and you will be able to connect." httpVerbs = utils.SetLiteral("CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE") + + unixEpoch = time.Unix(0, 0).UTC() + year2262Problem = time.Unix(0, 1<<63-1).UTC() // this is the maximum time for which (*time.Time).UnixNano() is well-defined ) // Server is the main Oragono server.