1.. _rfc-19: 2 3================================================================================ 4RFC 19: Safer memory allocation in GDAL 5================================================================================ 6 7Author: Even Rouault 8 9Contact: even.rouault@spatialys.com 10 11Status: Adopted, implemented 12 13Summary 14------- 15 16This document contains proposal on how to make GDAL safer (prevent 17crashes) when doing memory allocations. The starting point of this 18discussion is ticket #2075. 19 20Details 21------- 22 23In many places in GDAL source code, multiplications are done to compute 24the size of the memory buffer to allocate, like raster blocks, 25scanlines, whole image buffers, etc.. Currently no overflow checking is 26done, thus leading to potential allocation of not large enough buffers. 27Overflow can occur when raster dimensions are very large (this can be 28the case with a WMS raster source for example) or when a dataset is 29corrupted, intentionnaly or unintentionnaly. This can lead to latter 30crash. 31 32This RFC introduces new API to allocate memory when the computation of 33the size to allocate is based on multiplications. These new API report 34overflows when they occur. Overflows are detected by checking that 35((a*b)/b) == a. This does not require to make assumptions on the size of 36the variable types, their signedness, etc. 37 38:: 39 40 /** 41 VSIMalloc2 allocates (nSize1 * nSize2) bytes. 42 In case of overflow of the multiplication, or if memory allocation fails, a 43 NULL pointer is returned and a CE_Failure error is raised with CPLError(). 44 If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned. 45 CPLFree() or VSIFree() can be used to free memory allocated by this function. 46 */ 47 void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 ); 48 49 /** 50 VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes. 51 In case of overflow of the multiplication, or if memory allocation fails, a 52 NULL pointer is returned and a CE_Failure error is raised with CPLError(). 53 If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned. 54 CPLFree() or VSIFree() can be used to free memory allocated by this function. 55 */ 56 void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 ); 57 58The behavior of VSIMalloc2 and VSIMalloc3 is consistent with the 59behavior of VSIMalloc. Implementation of already existing memory 60allocation API (CPLMalloc, CPLCalloc, CPLRealloc, VSIMalloc, VSICalloc, 61VSIRealloc) will not be changed. 62 63:ref:`rfc-8` will be 64updated to promote new API for safer memory allocation. For example 65using VSIMalloc2(x, y) instead of doing CPLMalloc(x \* y) or VSIMalloc(x 66\* y). 67 68Implementation steps 69-------------------- 70 711. Introduce the new API in gdal/port 72 732. Use the new API in GDAL core where it is relevant. The following 74 files have been identified as candidates : 75 gcore/gdalnodatamaskband.cpp, gcore/overview.cpp, 76 gcore/gdaldriver.cpp, gcore/gdalrasterblock.cpp 77 783. Use the new API in GDAL drivers. This step can be done incrementally. 79 Transition from CPL to VSI allocation can be necessary in some cases 80 too. Candidate drivers : Idrisi, PNG, GXF, BSB, VRT, MEM, JP2KAK, 81 RPFTOC, AIRSAIR, AIGRIB, XPM, USGDEM, BMP, GSG, HFA, AAIGRID. (See 82 gdal_svn_trunk_use_vsi_safe_mul_in_frmts.patch in ticket #2075) 83 84Even Rouault will implement the changes described in this RFC for the 85GDAL 1.6.0 release. 86 87Voting history 88-------------- 89 90+1 from all PSC members (FrankW, DanielM, HowardB, TamasS, AndreyK) 91