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