cfilebuffer-overflow

Overflow when reading a file


When reading a simple file, I keep overflowing and reading bytes out of the file despite making sure I get the size of the file in bytes prior to the read.

Here is my current code:

FILE* file;
int error_no = fopen_s(&file, filepath, "r");

if (error_no != 0 || file == 0) {
    std::cout << "Error whilst reading file: " + error_no;
}

fseek(file, 0, SEEK_END);
size_t size = ftell(file);

char* fileAsString = (char*) malloc(size+1);

fseek(file, 0, SEEK_SET);
fread(fileAsString, 1, size, file);

fileAsString[size] = 0;

std::cout << "\n" << size << "\n";
std::cout << fileAsString;

fclose(file);

I am expecting to open the file, push the stream to the end of the file and use ftell to find the number of characters in the file.

Then I make a string buffer to copy the file's content into.

Then finally I reset the file stream and read it into my string buffer. I complete this by adding the end-of-string character at the end of the buffer.

Sadly this is what I get:

114
#version 330 core

layout(location = 0) out vec4 color;

void main()
{
        color = vec4(1.0, 0.0, 0.0, 1.0);
}═══════

I checked and the file contains 107 characters, which explains the 114 length and 7 '=' characters that shouldn't be there.

The actual file contents are:

#version 330 core

layout(location = 0) out vec4 color;

void main()
{
    color = vec4(1.0, 0.0, 0.0, 1.0);
}

Hope this is clear enough!


Solution

  • When you read a file with "r" mode, you are reading in text mode and your two-byte \r\n line endings are being converted to \n strings in memory. But ftell is returning the length of the file in bytes (with each newline counting for two bytes). But you are marking the end of the string (by setting a null character) according to how many bytes were in the file, as opposed to how many characters are in the string. Since you have placed your null terminator past the end of the string, you have one character of junk for each newline in your original file.

    Instead, you probably want to preserve the bytes of the original file. To do this, try opening the file in "rb" mode to read it in binary mode which should prevent it from changing \r\n in the file to \n in the string in memory.