Search code examples
coptimizationc89

Is behavioral change due to optimizations with "implementation defined" legal or expected?


I've been watching a thread on the OpenSSL mailing list. The thread is titled CBC ciphers + TLS 1.0 protocol does not work in OpenSSL 1.0.2d.

OpenSSL 1.0.2d had intermittent problems due to the following. It showed up under Microsoft's WinCE compiler. The idea is to propagate the high bit to all other bits:

#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) )
#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))

static unsigned char constant_time_eq_8(unsigned a, unsigned b)
{
    unsigned c = a ^ b;
    c--;
    return DUPLICATE_MSB_TO_ALL_8(c);
}

OpenSSL attempts to follow C89. I believe this is implementation defined behavior due to shifting of a negative value on a 2's compliment machine.

However, what the OP found was it was affected by optimizations. Without optimizations the code produced correct results. With optimizations the code produced incorrect results.

My question is, when relying on implementation defined behavior, is it legal or expected to see results change depending on optimizations?


Solution

  • Implementation-defined means that the implementation must document the behaviour:

    implementation-defined behavior

    unspecified behavior where each implementation documents how the choice is made

    So, consult the documentation for which compiler you have observed the unexpected results on. The documentation may or may not specify the behaviour you observed.

    If the observed behaviour differs from the documentation then confirm it with a SSCCE and file a bug report. If the documentation is not present then file a bug report for missing required documentation.