From ef5c826c74c160d33d4b79b23d564f944d16a9dd Mon Sep 17 00:00:00 2001
From: sebres <info@sebres.de>
Date: Fri, 7 May 2021 01:16:48 +0200
Subject: [PATCH] fixes search for the best datepattern (gh-3020) - e. g. if
 line is too short, boundaries check for previously known unprecise pattern
 may fail on incomplete lines (logging break-off, no flush, etc)

---
 fail2ban/server/datedetector.py         |  4 ++--
 fail2ban/tests/fail2banregextestcase.py | 12 +++++++++++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/fail2ban/server/datedetector.py b/fail2ban/server/datedetector.py
index ecc9d93599..b90e1b2642 100644
--- a/fail2ban/server/datedetector.py
+++ b/fail2ban/server/datedetector.py
@@ -365,10 +365,10 @@ def matchTime(self, line):
 				# with space or some special char), otherwise possible collision/pattern switch:
 				if ((
 					line[distance-1:distance] == self.__lastPos[1] or
-						(line[distance] == self.__lastPos[2] and not self.__lastPos[2].isalnum())
+						(line[distance:distance+1] == self.__lastPos[2] and not self.__lastPos[2].isalnum())
 					) and (
 					line[endpos:endpos+1] == self.__lastEndPos[2] or
-						(line[endpos-1] == self.__lastEndPos[1] and not self.__lastEndPos[1].isalnum())
+						(line[endpos-1:endpos] == self.__lastEndPos[1] and not self.__lastEndPos[1].isalnum())
 				)):
 					# search in line part only:
 					log(logLevel-1, "  boundaries are correct, search in part %r", line[distance:endpos])
diff --git a/fail2ban/tests/fail2banregextestcase.py b/fail2ban/tests/fail2banregextestcase.py
index 85fe4f150f..1c55e227dc 100644
--- a/fail2ban/tests/fail2banregextestcase.py
+++ b/fail2ban/tests/fail2banregextestcase.py
@@ -384,7 +384,17 @@ def testNoDateTime(self):
 			"Found a match but no valid date/time found",
 			"Match without a timestamp:", all=True)
 
-		self.pruneLog()
+	def testIncompleteDateTime(self):
+		# datepattern in followed lines doesn't match previously known pattern + line is too short
+		# (logging break-off, no flush, etc):
+		self.assertTrue(_test_exec(
+			'-o', 'Found-ADDR:<ip>',
+			'192.0.2.1 - - [02/May/2021:18:40:55 +0100] "GET / HTTP/1.1" 302 328 "-" "Mozilla/5.0" "-"\n'
+			'192.0.2.2 - - [02/May/2021:18:40:55 +0100\n'
+			'192.0.2.3 - - [02/May/2021:18:40:55',
+			'^<ADDR>'))
+		self.assertLogged(
+			"Found-ADDR:192.0.2.1", "Found-ADDR:192.0.2.2", "Found-ADDR:192.0.2.3", all=True)	
 
 	def testFrmtOutputWrapML(self):
 		unittest.F2B.SkipIfCfgMissing(stock=True)
