从文件中读取索引是否存在缓冲区溢出漏洞?
Is reading an index from a file a buffer overflow vulnerability?
最近使用静态分析工具(Checkmarx)扫描了一个老游戏引擎的源代码,看是否存在缓冲区溢出漏洞。我很惊讶地看到以下代码被标记为缓冲区溢出的可能来源:
// 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];
}
静态分析工具称之为 "Index from input buffer overflow vulnerability"。它看到 int i
的范围从 0 到 numVertices
,这是从文件中读取的,它认为这可能会导致缓冲区溢出。但在这种特殊情况下真的有可能吗? numVertices
用于分配缓冲区的大小,所以我看不出缓冲区溢出是如何发生的。如果可能的话,你会如何预防呢?请注意,我无法更改缓冲区的类型,因为那样会破坏太多代码。
感谢您提供任何信息!
警告完全正确。您正在从外部源读取已签名的 int
,然后在调用 reserve
和 fread
时将其提升为 size_t
。由于 size_t
是无符号类型,如果您从文件中读取的值是负数,则提升为 size_t
时的结果值将远大于 numVertices
的绝对值在大多数平台上。结果是您将尝试保留和读取大量向量。如果这两个操作成功,您将尝试 new
一个负数组大小。如果你做到这一点,你的 for
循环保证永远不会执行。
修复方法是将值作为无符号整数读取,或者更好的是 size_t
,尽管这将需要您更改写入该值的代码。另一种选择是至少验证该值。信任来自外部来源的数据是成为本周漏洞的好方法。
最近使用静态分析工具(Checkmarx)扫描了一个老游戏引擎的源代码,看是否存在缓冲区溢出漏洞。我很惊讶地看到以下代码被标记为缓冲区溢出的可能来源:
// 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];
}
静态分析工具称之为 "Index from input buffer overflow vulnerability"。它看到 int i
的范围从 0 到 numVertices
,这是从文件中读取的,它认为这可能会导致缓冲区溢出。但在这种特殊情况下真的有可能吗? numVertices
用于分配缓冲区的大小,所以我看不出缓冲区溢出是如何发生的。如果可能的话,你会如何预防呢?请注意,我无法更改缓冲区的类型,因为那样会破坏太多代码。
感谢您提供任何信息!
警告完全正确。您正在从外部源读取已签名的 int
,然后在调用 reserve
和 fread
时将其提升为 size_t
。由于 size_t
是无符号类型,如果您从文件中读取的值是负数,则提升为 size_t
时的结果值将远大于 numVertices
的绝对值在大多数平台上。结果是您将尝试保留和读取大量向量。如果这两个操作成功,您将尝试 new
一个负数组大小。如果你做到这一点,你的 for
循环保证永远不会执行。
修复方法是将值作为无符号整数读取,或者更好的是 size_t
,尽管这将需要您更改写入该值的代码。另一种选择是至少验证该值。信任来自外部来源的数据是成为本周漏洞的好方法。