0

I'm reading a file a RSA encrypted binary file which contains nulls. The file is encrypted and saved in python, then read in c++.

Python treats it fine, reading and writing it just displays the nulls as

...\x94\x00\xbf...

However, in my C++ it terminates it early.


FILE* fpy = fopen("test.txt", "rb");
unsigned char* signPy = (unsigned char*)malloc(256);
fread(signPy, 1, 256, fpy);
fclose(fpy);
cout << signPy << endl;

The file is exactly 256 bytes so I know I'm allocating enough memory. Using fread it terminates at the first null. Any help would be appreciated.

ZWang
  • 832
  • 5
  • 14
  • 5
    Are you 100% sure about that? Because my guess would be that you are only looking at the output from `cout` which will terminate at the first null, since that is used for terminating C-Style strings. Try to iterate over the memory instead with a for loop and printing each element – UnholySheep Feb 28 '22 at 14:23
  • Are you doing this in C++ or C? Because you are using C file handling... – Dúthomhas Feb 28 '22 at 14:25
  • @UnholySheep I have been using cout, thanks im going to try that – ZWang Feb 28 '22 at 14:32
  • 1
    @UnholySheep You're right, it was there all along! – ZWang Feb 28 '22 at 14:37
  • 1
    Some options to [print binary data](https://stackoverflow.com/questions/10599068/how-do-i-print-bytes-as-hexadecimal). – jarmod Feb 28 '22 at 14:40

2 Answers2

1

Continuing the code:

FILE* fpy = fopen("test.txt", "rb");
unsigned char* signPy = (unsigned char*)malloc(256);
int const count = fread(signPy, 1, 256, fpy);
fclose(fpy);
// cout << signPy << endl;
for (int i = 0; i < count; ++i)
  putchar(signPy[i]);

Problem was that cout will treat signPy as null terminated char buffer, so it will stop printing more characters once null is encountered.

You can print the data in binary format as well, as suggested in comments.

g-217
  • 2,069
  • 18
  • 33
0

Not really an answer to your actual problem, but since this is C++, here’s how to do it in C++:

std::string signPy( 256, '\0' );
{
  std::ifstream fpy( "test.txt", std::ios::binary );
  fpy.read( (char *)signPy.c_str(), signPy.size() );
}

That creates a string of 256 bytes initialized to zeros.
Then it creates an input file stream and reads up to 256 bytes (fewer if the file is too small).
Notice also that the file object is a temporary, created and automatically destroyed in its own local context.

To print it the way your example lists it (as a string of C-escape sequences):

{
  std::ostringstream oss;
  oss << std::hex;
  for (unsigned c : signPy)
    oss << "\\x" << std::setfill('0') << std::setw( 2 ) << (c & 0xFF);
  std::cout << oss.str() << "\n";
}

There are a multitude of other ways, but a simple loop here using a temporary stream is about as simple as you can get, even if it is ugly. You can make life prettier and shorter at the output point, but that requires additional code elsewhere.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • I wouldn't store binary data in a `std::string`, personally. Although it works, embedded nul's can cause nasty surprises. From C++17 on, I would go for `std::vector ` instead. – Paul Sanders Feb 28 '22 at 15:25
  • It was a toss-up which to use in my example, but `std::string` is specifically designed to work just fine with embedded nulls and other eight-bit data. The caveats are not a problem with `std::string`, rather a problem that exists in the language itself: signedness of a `char` and special handling related to specific characters when using a textual output mode _and_ the very same problem that `char *` has when treating it as such. As with everything in C and C++, know your tools and how to use them, I guess. – Dúthomhas Mar 01 '22 at 00:49
  • Sure, but that's just the point I was trying to make. Embedding nuls in a `std::string` is a trap for the unwary. – Paul Sanders Mar 01 '22 at 10:52