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) 是的。
实施步骤
在gdal/port中引入新的API
在GDAL core中使用新的API。以下文件已被确定为候选文件:gcore/gdalnodatamaskband.cpp、gcore/overview.cpp、gcore/gdaldriver.cpp、gcore/gdalrasterblock.cpp
在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名