RFC 19:GDAL中更安全的内存分配

作者:连鲁奥

联系方式:even.rouault@spatialys.com

状态:通过、实施

总结

本文档包含如何使GDAL在进行内存分配时更安全(防止崩溃)的建议。讨论的起点是2075票。

细节

在GDAL源代码中的许多地方,都会进行乘法运算来计算要分配的内存缓冲区的大小,如栅格块、扫描线、整个图像缓冲区等。。目前没有进行溢出检查,因此可能导致分配的缓冲区不够大。当栅格尺寸非常大(例如,WMS栅格源可能会出现这种情况)或数据集损坏时,可能会发生溢出。这可能导致后面的崩溃。

当要分配的大小是基于乘法计算时,这个RFC引入了新的API来分配内存。这些新的API报告在发生时溢出。通过检查((a*b)/b)==a来检测溢出。这不需要对变量类型的大小、它们的符号性等进行假设。

/**
 VSIMalloc2 allocates (nSize1 * nSize2) bytes.
 In case of overflow of the multiplication, or if memory allocation fails, a
 NULL pointer is returned and a CE_Failure error is raised with CPLError().
 If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
 CPLFree() or VSIFree() can be used to free memory allocated by this function.
*/
void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 );

/**
 VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
 In case of overflow of the multiplication, or if memory allocation fails, a
 NULL pointer is returned and a CE_Failure error is raised with CPLError().
 If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
 CPLFree() or VSIFree() can be used to free memory allocated by this function.
*/
void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 );

VSIMalloc2和VSIMalloc3的行为与VSIMalloc的行为一致。已经存在的内存分配API(CPLMalloc、CPLCalloc、CPLRealloc、VSIMalloc、VSICalloc、VSIRealloc)的实现不会更改。

RFC 8:开发人员指南 将更新以升级新的API以实现更安全的内存分配。例如,使用VSIMalloc2(x,y)而不是CPLMalloc(x * y) 或VSIMalloc(x * y) 是的。

实施步骤

  1. 在gdal/port中引入新的API

  2. 在GDAL core中使用新的API。以下文件已被确定为候选文件:gcore/gdalnodatamaskband.cpp、gcore/overview.cpp、gcore/gdaldriver.cpp、gcore/gdalrasterblock.cpp

  3. 在GDAL驱动程序中使用新的API。这一步可以逐步完成。在某些情况下,从CPL到VSI分配的转换也是必要的。候选驱动程序:Idrisi、PNG、GXF、BSB、VRT、MEM、JP2KAK、RPFTOC、AIRSAIR、AIGRIB、XPM、USGDEM、BMP、GSG、HFA、AAIGRID。(请参阅gdal_svn_trunk_use_vsi_safe_mul_in_frmts.patch in ticket#2075)

即使是Rouault也将实现本RFC中描述的GDAL 1.6.0版本的更改。

投票历史

+所有PSC成员(FrankW、DanielM、HowardB、TamasS、AndreyK)各1名