0

I'm writing a C++ class to add a digital signature to a PDF, using OpenSSL to generate a SHA1 hash, which I then print to a file:

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((unsigned char *)temp.c_str(), temp.size(), hash);

std::ofstream fout("resources/hash.out", std::ios::binary);
fout << hash;
fout.close();

This code works as expected in Debug mode. In Release mode, fout << hash prints 30 instead of SHA_DIGEST_LENGTH = 20 bytes, the last 10 of which look like garbage (maybe buffer overflow?)

My current workaround is to print each character instead of streaming:

for (int i=0; i<SHA_DIGEST_LENGTH; ++i)
    fout.put(hash[i]);  

Which works in both build modes, but I'm curious what could cause the stream operator to misread the length of the string. Does anybody have any thoughts?

For the record, I'm compiling with MSVC++ 12 (x86_amd64).

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Chris
  • 298
  • 4
  • 8

2 Answers2

3

There is a stream-inserter for NUL-terminated strings, which is the one selected.

But you are trying to output an array of fixed length containing arbitrary bytes, which is something completely different, leading to UB.

Just use memberfunction write(buffer, size) instead, which is designed for that.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
2

You need to take into account that OpenSSL's SHA methods don't null-terminate the output. The normal operator << requires null-termination, so you cannot use it directly.

To print this "unterminated" string with C++ streams, see e.g.

C++ non null terminated char array outputting

for printf e.g.

Using printf with a non-null terminated string

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182