get_timer: don't use uninitialized memory

get_timer with reset=1 is called both to initialize a
timer object and to reset an already-initialized object. In an
initial call, the content of the data structure is indeterminate, so
the code should not read from it. This could crash if signed overflows
trap, for example.

As a consequence, on reset, we can't return the previously elapsed
time as was previously done on Windows. Return 0 as was done on Unix.
This commit is contained in:
Gilles Peskine 2017-10-16 19:33:06 +02:00
parent de896ebd26
commit 2484ffeb81
2 changed files with 24 additions and 22 deletions

View File

@ -44,6 +44,7 @@ Bugfix
* Fix crash when calling mbedtls_ssl_cache_free() twice. Found by * Fix crash when calling mbedtls_ssl_cache_free() twice. Found by
MilenkoMitrovic, #1104 MilenkoMitrovic, #1104
* Fix mbedtls_timing_alarm(0) on Unix. * Fix mbedtls_timing_alarm(0) on Unix.
* Fix use of uninitialized memory in mbedtls_timing_get_timer when reset=1.
Changes Changes
* Extend cert_write example program by options to set the CRT version * Extend cert_write example program by options to set the CRT version

View File

@ -234,22 +234,24 @@ volatile int alarmed = 0;
unsigned long get_timer( struct hr_time *val, int reset ) unsigned long get_timer( struct hr_time *val, int reset )
{ {
unsigned long delta;
LARGE_INTEGER offset, hfreq;
struct _hr_time *t = (struct _hr_time *) val; struct _hr_time *t = (struct _hr_time *) val;
QueryPerformanceCounter( &offset );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( 1000 *
( offset.QuadPart - t->start.QuadPart ) ) /
hfreq.QuadPart );
if( reset ) if( reset )
{
QueryPerformanceCounter( &t->start ); QueryPerformanceCounter( &t->start );
return( 0 );
}
else
{
unsigned long delta;
LARGE_INTEGER now, hfreq;
QueryPerformanceCounter( &now );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
/ hfreq.QuadPart );
return( delta ); return( delta );
} }
}
/* It's OK to use a global because alarm() is supposed to be global anyway */ /* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs; static DWORD alarmMs;
@ -280,24 +282,23 @@ void m_sleep( int milliseconds )
unsigned long get_timer( struct hr_time *val, int reset ) unsigned long get_timer( struct hr_time *val, int reset )
{ {
unsigned long delta;
struct timeval offset;
struct _hr_time *t = (struct _hr_time *) val; struct _hr_time *t = (struct _hr_time *) val;
gettimeofday( &offset, NULL );
if( reset ) if( reset )
{ {
t->start.tv_sec = offset.tv_sec; gettimeofday( &t->start, NULL );
t->start.tv_usec = offset.tv_usec;
return( 0 ); return( 0 );
} }
else
delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 {
+ ( offset.tv_usec - t->start.tv_usec ) / 1000; unsigned long delta;
struct timeval now;
gettimeofday( &now, NULL );
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
return( delta ); return( delta );
} }
}
#if defined(INTEGRITY) #if defined(INTEGRITY)
void m_sleep( int milliseconds ) void m_sleep( int milliseconds )