简体   繁体   中英

Is reading an index from a file a buffer overflow vulnerability?

I recently used a static analysis tool (Checkmarx) to scan the source code of an old game engine to see if there are any buffer overflow vulnerabilities in it. I was surprised to see that the following code was flagged as a possible source of buffer overflows:

// Get a pointer to a file that describes a 3D model
std::string filename = "my_3D_model.obj"
FILE* stream;
fopen_s(&stream, filename.c_str(), "rb");

// Read the number of vertices that make up the 3D model
int numVertices = 0;
fread(&numVertices, sizeof(int), 1, stream);

// Read the vertices and store them in a vector
// The static analysis tool doesn't complain about the use of numVertices to
// reserve space and to read from the file
std::vector<Vertex> vertices;
vertices.reserve(numVertices);
fread(vertices.data(), sizeof(Vertex), numVertices, stream);

// ...

// Copy the vertices from the vector to an array that has been allocated on the heap
// The static analysis tool complains because numVertices, which was read from a file,
// is being used as an index
Vertex* meshVertices = new Vertex[numVertices];
for (int i = 0; i < numVertices; i++)
{
    meshVertices[i] = vertices[i];
}

The static analysis tool calls this an "Index from input buffer overflow vulnerability". It sees that int i is ranging from 0 to numVertices , which was read from a file, and it thinks that that might cause a buffer overflow. But is it really possible in this particular case? numVertices is being used to allocate the size of the buffers, so I don't see how a buffer overflow could occur. And if it is possible, how would you prevent it? Note that I can't change the types of the buffers because that would break too much code.

Thanks for any information!

The warning is absolutely correct. You're reading a signed int from an external source and then promoting it to a size_t when you call reserve and fread . Since size_t is an unsigned type, if the value you read from the file is a negative number the resulting value when promoted to size_t is going to be much larger than the absolute value of numVertices on most platforms. The result is you're going to try to reserve and read a huge number of vectors. If those two operations succeed, you're then going to try to new a negative array size. Your for loop is guaranteed never to execute if you get that far.

The fix is to read the value as an unsigned int, or better yet a size_t , although that will require you to alter the code that writes the value. Another option is to at least validate the value. Trusting data from external sources is a great way to become this week's exploit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM