Dear All,

Compiling master 20140721 both for w32 (with VC++ 9.0 express) and WCE/ARMv4 target (with EVC4sp4 compiler + WCE 420 SDK),
I found those two cast issues :


1/ crypto/bn/bn_nist.c, function BN_nist_mod_func(...)

clarm.exe /Fotmp32dll_ARMV4\bn_nist.obj  -Iinc32 -Itmp32dll_ARMV4 /O1i /
W3 /WX /GF /Gy /nologo -DUNICODE -D_UNICODE -DOPENSSL_SYSNAME_WINCE -DWIN32_LEAN _AND_MEAN -DL_ENDIAN -DDSO_WIN32 -DNO_CHMOD -DOPENSSL_SMALL_FOOTPRINT -D_WIN32_W CE=420 -DUNDER_CE=420 -DWCE_PLATFORM_STANDARDSDK -DARM -D_ARM_ -DARMV4 -I..\..\. .\wcecompat\v12\patched3emu/include /MC -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPEN SSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_STATIC_ENGINE /Zi /Fdtmp32dll_ARMV4/
lib -D_WINDLL -D_DLL  -DOPENSSL_BUILD_SHLIBCRYPTO -c .\crypto\bn\bn_nist.c
bn_nist.c
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
134) : error C2220: warning treated as error - no object file generated
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
134) : warning C4550: expression evaluates to a function which is missing an arg
ument list
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
136) : warning C4550: expression evaluates to a function which is missing an arg
ument list
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
138) : warning C4550: expression evaluates to a function which is missing an arg
ument list
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
140) : warning C4550: expression evaluates to a function which is missing an arg
ument list
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\bn\bn_nist.c(1
142) : warning C4550: expression evaluates to a function which is missing an arg
ument list
NMAKE : fatal error U1077: 'clarm.exe' : return code '0x2'
Stop.

CAUSE : The problem comes from the fact that the expressions like "return BN_nist_mod_192" are interpreted by EVC4sp4 compiler as function calls with missing args.

FIX : just use typedef and explicit function pointers to avoid the ambiguity, like this :

typedef int (* pBN_nist_mod_func_t) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);

int (*BN_nist_mod_func(const BIGNUM *p))(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx)
    {
    pBN_nist_mod_func_t pfn;

    if (BN_ucmp(&_bignum_nist_p_192, p) == 0)
        pfn = BN_nist_mod_192;
    else if (BN_ucmp(&_bignum_nist_p_224, p) == 0)
        pfn = BN_nist_mod_224;
    else if (BN_ucmp(&_bignum_nist_p_256, p) == 0)
        pfn = BN_nist_mod_256;
    else if (BN_ucmp(&_bignum_nist_p_384, p) == 0)
        pfn = BN_nist_mod_384;
    else if (BN_ucmp(&_bignum_nist_p_521, p) == 0)
        pfn = BN_nist_mod_521;
    else pfn = (pBN_nist_mod_func_t) 0;
    return pfn;
    }

By the way I suggest that functions returning "pointer to functions" also use those typedefs in their prototypes, to ease the understanding and maintenance of the code,
so for example the prototype :

int (*BN_nist_mod_func(const BIGNUM *p))(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx)
{...}

could/SHOULD be replaced by :

pBN_nist_mod_func_t BN_nist_mod_func(const BIGNUM *p)
{...}

using the pBN_nist_mod_func_t "pointer to function" type defined a few lines above.

I also suggest that something like this go in some coding rules guide one day... More precisely I suggest that ANY sophisticated "pointer to function" declaration be explicitely using "pointer to function" type-defs.


2/ crypto\x509v3\v3_scts.c, function timestamp_print(...), line 151, needs a cast to long for the 4th parameter of the ASN1_GENERALIZEDTIME_adj(...) function call:

clarm.exe /Fotmp32dll_ARMV4\v3_scts.obj -Iinc32 -Itmp32dll_ARMV4 /O1i / W3 /WX /GF /Gy /nologo -DUNICODE -D_UNICODE -DOPENSSL_SYSNAME_WINCE -DWIN32_LEAN _AND_MEAN -DL_ENDIAN -DDSO_WIN32 -DNO_CHMOD -DOPENSSL_SMALL_FOOTPRINT -D_WIN32_W CE=420 -DUNDER_CE=420 -DWCE_PLATFORM_STANDARDSDK -DARM -D_ARM_ -DARMV4 -I..\..\. .\wcecompat\v12\patched3emu/include /MC -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPEN SSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_STATIC_ENGINE /Zi /Fdtmp32dll_ARMV4/ lib -D_WINDLL -D_DLL -DOPENSSL_BUILD_SHLIBCRYPTO -c .\crypto\x509v3\v3_scts.c
v3_scts.c
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\x509v3\v3_scts
.c(151) : error C2220: warning treated as error - no object file generated
c:\users\pdelaage\dvts\contrib\openssl\snap20140721\patch1\crypto\x509v3\v3_scts
.c(151) : warning C4244: 'function' : conversion from 'unsigned __int64 ' to 'lo
ng ', possible loss of data
NMAKE : fatal error U1077: 'clarm.exe' : return code '0x2'
Stop.

CAUSE :
this is  related to the prototype in crypto/asn1/asn1.h :
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
         time_t t, int offset_day, long offset_sec);

the 4th parameter must be long, while it is set as something equivalent to "__int64" at calling time in crypto\x509v3\v3_scts.c, function timestamp_print(...).

FIX : explicit cast to 'long" here :
"....
ASN1_GENERALIZEDTIME_adj(gen, (time_t)0,
                    (int)(timestamp / 86400000),
                    (long) ((timestamp % 86400000) / 1000));
..."

It is interesting to note that this W32/WCE bug is seen by MS EVC4sp4 compiler, and not by MS VC++ 9.0 express edition compiler....
so that, in that example, testing for WCE can help to find bugs in win32...
This is just to mention that compiling the same code in various platforms and with various tools, can help to improve it for any others, good to remind in those times of reflexions about roadmap and platform (un)support.


3/ crypto\x509v3\v3_scts.c, line 65, relating to SCT_TIMESTAMP type definition :

Line 65 is defined like this  :
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)

But in that case, compiling for WCE leads to get "#define SCT_TIMESTAMP unsigned long long"

while the W32 version "#define SCT_TIMESTAMP unsigned __int64" should be ok (as EVC4 supports __int64 for around 10 years...) :

So I suggest that we change the #define at line 65 like this :
#if (defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)) && !defined(__MINGW32__)

In that particular case, recent version of MSVC support "long long" as being equivalent to __int64, ok, but this is not documented at all in MS EVC4, although it is in fact also supported there (yes it is), so support is just hazardous... so it would be safier in WCE to get the __int64 definition instead of "long long".

I guess that this kind of problem may occur in many places in the code, for various platforms, so that isolating platform specifics in port-dedicated sources may help...
at least to deal with some basic types declarations.

For coding rules future guide, I would then also suggest that for TYPE definition, we use typedef instead of #define, to get stronger type checking.


Yours sincerely,
Pierre Delaage


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to