64 bits OpenSSL compilation and 32/64 bits PERL dependencies

I sent the following email to OpenSSL mailing list the Mar 19, 2015:

When compiling a 64 bit OpenSSL 1.0.2a with a 32 bit PERL interpreter I get this error:

./config zlib-dynamic shared
make
[...]
/usr/local/bin/perl asm/ghash-x86_64.pl elf > ghash-x86_64.s
Integer overflow in hexadecimal number at
asm/../../perlasm/x86_64-xlate.pl line 201, <> line 890.
gcc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include  -fPIC
-DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_REENTRANT
-DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -O3 -Wall -DL_ENDIAN
-DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5
-DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM
-DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
-DECP_NISTZ256_ASM -c  -o ghash-x86_64.o ghash-x86_64.s
ghash-x86_64.s: Assembler messages:
ghash-x86_64.s:890: Error: junk `.15473355479995e+19' after expression
<builtin>: recipe for target 'ghash-x86_64.o' failed
make[2]: *** [ghash-x86_64.o] Error 1

In line 890 I have this:

subq    $48,%rcx
movq    $1.15473355479995e+19,%rax  <<<<<<<<<<<<<<<<<<
movdqu  48(%rsi),%xmm14
movdqu  64(%rsi),%xmm15

Comparing that line in other machines where compilation is done correctly, I see this:

movq    $11547335547999543296,%rax

Notice that "11547335547999543296" is approximately 1.15473355479995e+19 in scientific notation.

When doing "perl -e 'print(11547335547999543296)' I get:

11547335547999543296

in one machine (64 bits), but

1.15473355479995e+19

in the other machine (32 bits).

The number is being promoted to scientific notation and compilation will fail.

Yes, in Solaris I can mix 32 and 64 bit binaries in the same running system. It is standard practice and the reason I am compiling OpenSSL both in 32 and in 64 bits.

Replacing the scientific notation value with "11547335547999543296" the code compiles correctly and the tests complete 100% OK.

In the 64 bit PERL version "11547335547999543296" is printed correctly as an integer but "21547335547999543296" (first digit changed) is printed as 2.15473355479995e+19. I think that depending of implementation details (the value when an integer is "promoted" to floating point) of the PERL interpreter is bad practice and should be avoided. Maybe using literal string, of splitting the number in two halfs.

I had no useful reply in the mailing list. I patched the source code by hand and forgot about this.

Then OpenSSL 1.0.2b was published and I had the very same issue. I decided to bite the bullet and solve the issue myself.

I compile my own Perl interpreter in my Solaris machines. The result is different compared with the system version:

$ /usr/local/bin/perl -e 'print(11547335547999543296); print("\n")'
1.15473355479995e+19
$ /usr/bin/perl -e 'print(11547335547999543296); print("\n")'
11547335547999543296

You can easily see the difference between versions.

After quite a few tests I found the compile time configuration I need:

  • Try to use 64-bit integers, if available? YES

I get the result I want when compiling a new Perl interpreter with that not default configuration:

$ /usr/local/bin/perl -e 'print(11547335547999543296); print("\n")'
11547335547999543296

Anyway I think that this Perl idiosincracy dependency is problematic and fragile. Building that constant in a 32/64 bits independent way should be the right thing to do.