From 53664cb86c7e331bea7e9d4711d029e08f939843 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Thu, 18 Sep 2008 00:50:28 +0000
Subject: [PATCH] ITS#5668

---
 CHANGES                    |  1 +
 libraries/liblutil/utils.c | 39 ++++++++++++++++++++++++--------------
 2 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/CHANGES b/CHANGES
index 7746eb8171..6cb523ab68 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,7 @@ OpenLDAP 2.4 Change Log
 OpenLDAP 2.4.12 Engineering
 	Fixed libldap TLS_CRLFILE (ITS#5677)
 	Fixed liblutil executables on Windows (ITS#5604)
+	Fixed liblutil microsecond overflows on Windows (ITS#5668)
 	Fixed librewrite memory handling (ITS#5691)
 	Fixed slapd aci performance (ITS#5636)
 	Fixed slapd aci's with sets (ITS#5627)
diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c
index 63b0f3802a..8a199f85dd 100644
--- a/libraries/liblutil/utils.c
+++ b/libraries/liblutil/utils.c
@@ -303,41 +303,52 @@ lutil_gettime( struct lutil_tm *tm )
 	GetSystemTime( &st );
 	QueryPerformanceCounter( &count );
 
+	/* It shouldn't ever go backwards, but multiple CPUs might
+	 * be able to hit in the same tick.
+	 */
+	if ( count.QuadPart <= prevCount.QuadPart ) {
+		subs++;
+	} else {
+		subs = 0;
+		prevCount = count;
+	}
+
 	/* We assume Windows has at least a vague idea of
 	 * when a second begins. So we align our microsecond count
 	 * with the Windows millisecond count using this offset.
 	 * We retain the submillisecond portion of our own count.
+	 *
+	 * Note - this also assumes that the relationship between
+	 * the PerformanceCouunter and SystemTime stays constant;
+	 * that assumption breaks if the SystemTime is adjusted by
+	 * an external action.
 	 */
 	if ( !cFreq.QuadPart ) {
 		long long t;
 		int usec;
 		QueryPerformanceFrequency( &cFreq );
 
-		t = count.QuadPart * 1000000;
-		t /= cFreq.QuadPart;
-		usec = t % 10000000;
-		usec /= 1000;
-		offset = ( usec - st.wMilliseconds ) * 1000;
-	}
+		/* just get sub-second portion of counter */
+		t = count.QuadPart % cFreq.QuadPart;
 
-	/* It shouldn't ever go backwards, but multiple CPUs might
-	 * be able to hit in the same tick.
-	 */
-	if ( count.QuadPart <= prevCount.QuadPart ) {
-		subs++;
-	} else {
-		subs = 0;
-		prevCount = count;
+		/* convert to microseconds */
+		t *= 1000000;
+		usec = t / cFreq.QuadPart;
+
+		offset = usec - st.wMilliseconds * 1000;
 	}
 
 	tm->tm_usub = subs;
 
 	/* convert to microseconds */
+	count.QuadPart %= cFreq.QuadPart;
 	count.QuadPart *= 1000000;
 	count.QuadPart /= cFreq.QuadPart;
 	count.QuadPart -= offset;
 
 	tm->tm_usec = count.QuadPart % 1000000;
+	if ( tm->tm_usec < 0 )
+		tm->tm_usec += 1000000;
 
 	/* any difference larger than microseconds is
 	 * already reflected in st
-- 
GitLab