UefiCpuPkg/MpLib: fix potential overflow issue.

Current calculate timeout logic may have overflow if the input
timeout value too large. This patch fix this potential overflow
issue.

V2: Use local variable instead of call GetPerformanceCounterProperties
twice. Also correct some comments.

Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
This commit is contained in:
Eric Dong 2017-08-21 14:40:44 +08:00
parent 714c260301
commit 48cfb7c0f4
1 changed files with 32 additions and 9 deletions

View File

@ -1001,6 +1001,9 @@ CalculateTimeout (
OUT UINT64 *CurrentTime OUT UINT64 *CurrentTime
) )
{ {
UINT64 TimeoutInSeconds;
UINT64 TimestampCounterFreq;
// //
// Read the current value of the performance counter // Read the current value of the performance counter
// //
@ -1016,17 +1019,37 @@ CalculateTimeout (
// //
// GetPerformanceCounterProperties () returns the timestamp counter's frequency // GetPerformanceCounterProperties () returns the timestamp counter's frequency
// in Hz. So multiply the return value with TimeoutInMicroseconds and then divide // in Hz.
//
TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL);
//
// Check the potential overflow before calculate the number of ticks for the timeout value.
//
if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) {
//
// Convert microseconds into seconds if direct multiplication overflows
//
TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000);
//
// Assertion if the final tick count exceeds MAX_UINT64
//
ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq);
return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds);
} else {
//
// No overflow case, multiply the return value with TimeoutInMicroseconds and then divide
// it by 1,000,000, to get the number of ticks for the timeout value. // it by 1,000,000, to get the number of ticks for the timeout value.
// //
return DivU64x32 ( return DivU64x32 (
MultU64x64 ( MultU64x64 (
GetPerformanceCounterProperties (NULL, NULL), TimestampCounterFreq,
TimeoutInMicroseconds TimeoutInMicroseconds
), ),
1000000 1000000
); );
} }
}
/** /**
Checks whether timeout expires. Checks whether timeout expires.