Home > Software engineering >  Why images can be uploaded with char array but not with equal std::istringstream in C ?
Why images can be uploaded with char array but not with equal std::istringstream in C ?

Time:03-19

Consider the code below for a second:

    char buffer[4000];
    size_t bytes = recv(fd, buffer, 4000, 0);
    write(pipefd[1], buffer, bytes);
    close(pipefd[1]);
    wait(NULL);

Here I read fd, write data to the pipe and close the pipe. This allows to eventually upload tiny images that can be rendered. However, if I do everything the same, only replace char array with std::istringstream, as in the example below:

    char buffer[4000];
    size_t bytes = recv(fd, buffer, 4000, 0);

    std::istringstream data(buffer);
    write(pipefd[1], data.str().c_str(), bytes);

    close(pipefd[1]);
    wait(NULL);

Then image is uploaded but cannot be rendered. (Via pipes this C program communicates with a php-cgi script).

Also:

if (strcmp(data.str().c_str(), buffer) == 0)
 // returns true

I am very curious as to why this could be the case.

CodePudding user response:

If you run on Windows, then C streams add carriage return \r after single \n automatically while reading and writing. The fix is simple

std::istringstream data(buffer, std::ios::binary);

MacOS is configurable for using any of \r, \n, \r\n. You should never expect what is used and always apply the stream mode std::ios::binary for binary data.

However the both code snippets are not valid, std::istringstream data(buffer) and std::string data(buffer) use bytes in data until first zero byte met.

CodePudding user response:

std::istringstream data(buffer);

This assumes buffer is a null-terminated string. Binary data typically contains 0x00 bytes, thus you would end up truncating the buffer contents.

Use this instead:

std::istringstream data(std::string(buffer, bytes), std::ios::binary);
  • Related