Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

    Background:
    The type, precision, and range of both time_t and clock_t are implementation defined. Local time zone and daylight savings time are also implementation defined. The Unix time standard can also vary slightly.. IE, the type of time_t and clock_t are precisely "It's a number guys!". It is therefore important to be very careful when using time_t and clock_t in C because assumptions can lead to problems ranging from errors in program timing to possible overflow from invalid type conversions. What follows are some recommendations that help one to avoid common pitfalls that cause security vulnerabilities.

    Recommendation #1:
    When comparing time_t, first cast the item you are comparing it with to a time_t 
        The first and most obvious error is to use the type time_t is defined to be on your system rather than time_t itself. Traditionally, time_t is set to be a signed 32 bit integer type on Unix systems, but the C99 standard only requires that time_t is an arithmetic type. It is a common error (and temptation) to declare a signed integer as the time for easy conversion; however, many more modern systems use time as a 64 bit type, and your code may be incompatible with such systems.use integers interchangeably with time_t. However, doing so could lead to invalid comparisons in your code.

    Non-Compliant Code

Code Block

int main(void)
{
    time_t now = time(NULL);
    if ( now \!= \-1 ) {
        fputs(ctime(&now), stdout);
    }
    return 0;

}

    The c standard mandates that time() return (time_t)(-1). Some systems may interpret (time_t)(-1) as something completely different from the integer  -1. This could lead to potential invalid comparison and therefore invalid output (or worse, depending on what else is put in the if statement). Therefore the correct code is as follows:

    Compliant Code

Code Block

int main(void)
{
    time_t now = time(NULL);
    if ( now \!= (time_t)-1 ) {
        fputs(ctime(&now), stdout);
    }
    return 0;

}

    In the code above the comparison will function as expected.

    Recommendation #2:
   

    It is also important to be mindful that as a result of time_t being implementation defined, performing arithmetic operations with integers or floating points may or may not change the time variable's type or overflow the variable. If on your system time_t is an integer, do not divide time_t by an integer if you want your code to work with other machines. In other words, when performing arithmetic operations on time_t, use other time_t's and not integers or floating points. The function mktime() can be used to generate time_t variables.  
    According to the C99 standard "The clock function returns the implementation's best approximation to the processor time used by the program since the beginning of an implementation-de?ned era related only to the program invocation. To determine the time in seconds, the value returned by the clock function should be divided by the value of the macro CLOCKS_PER_SEC..." However, the question remains as to what the proper returned type of this operation should be. If you wish to determine how long a certain process required to operate, the C99 standard recommends code of the following form:

Code Block
 clock_t begin, end;
mystery_t mystery;
begin=clock();
/* run process */
end=clock();
mystery = (end-begin)/CLOCKS_PER_SEC

...

- An article about a denial-of-service in 64bit microsoft time code. Read it here 

- Interesting time_t discussion from which I pulled my example code. Read it here