Coverage Report

Created: 2025-07-23 09:13

/src/gdal/fuzzers/gdal_fuzzer.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  Fuzzer
5
 * Author:   Even Rouault, even.rouault at spatialys.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a
11
 * copy of this software and associated documentation files (the "Software"),
12
 * to deal in the Software without restriction, including without limitation
13
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
 * and/or sell copies of the Software, and to permit persons to whom the
15
 * Software is furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included
18
 * in all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
 * DEALINGS IN THE SOFTWARE.
27
 ****************************************************************************/
28
29
#include <stddef.h>
30
#include <stdint.h>
31
32
#include <algorithm>
33
#include <vector>
34
35
#include "gdal.h"
36
#include "cpl_conv.h"
37
#include "cpl_string.h"
38
#include "cpl_vsi.h"
39
#include "gdal_alg.h"
40
#include "gdal_priv.h"
41
#include "gdal_frmts.h"
42
43
#ifndef REGISTER_FUNC
44
82
#define REGISTER_FUNC GDALAllRegister
45
#endif
46
47
#ifndef GDAL_SKIP
48
164
#define GDAL_SKIP "CAD"
49
#endif
50
51
#ifndef EXTENSION
52
2.33k
#define EXTENSION "bin"
53
#endif
54
55
#ifndef MEM_FILENAME
56
670k
#define MEM_FILENAME "/vsimem/test"
57
#endif
58
59
#ifndef GDAL_FILENAME
60
223k
#define GDAL_FILENAME MEM_FILENAME
61
#endif
62
63
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv);
64
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
65
66
int LLVMFuzzerInitialize(int * /*argc*/, char ***argv)
67
164
{
68
164
    const char *exe_path = (*argv)[0];
69
164
    if (CPLGetConfigOption("GDAL_DATA", nullptr) == nullptr)
70
164
    {
71
164
        CPLSetConfigOption("GDAL_DATA", CPLGetPathSafe(exe_path).c_str());
72
164
    }
73
164
    CPLSetConfigOption("CPL_TMPDIR", "/tmp");
74
164
    CPLSetConfigOption("DISABLE_OPEN_REAL_NETCDF_FILES", "YES");
75
    // Disable PDF text rendering as fontconfig cannot access its config files
76
164
    CPLSetConfigOption("GDAL_PDF_RENDERING_OPTIONS", "RASTER,VECTOR");
77
    // to avoid timeout in WMS driver
78
164
    CPLSetConfigOption("GDAL_WMS_ABORT_CURL_REQUEST", "YES");
79
164
    CPLSetConfigOption("GDAL_HTTP_TIMEOUT", "1");
80
164
    CPLSetConfigOption("GDAL_HTTP_CONNECTTIMEOUT", "1");
81
164
    CPLSetConfigOption("GDAL_CACHEMAX", "1000");  // Limit to 1 GB
82
#ifdef GTIFF_USE_MMAP
83
    CPLSetConfigOption("GTIFF_USE_MMAP", "YES");
84
#endif
85
86
164
#ifdef GDAL_SKIP
87
164
    CPLSetConfigOption("GDAL_SKIP", GDAL_SKIP);
88
164
#endif
89
164
    REGISTER_FUNC();
90
91
164
    return 0;
92
164
}
LLVMFuzzerInitialize
Line
Count
Source
67
82
{
68
82
    const char *exe_path = (*argv)[0];
69
82
    if (CPLGetConfigOption("GDAL_DATA", nullptr) == nullptr)
70
82
    {
71
82
        CPLSetConfigOption("GDAL_DATA", CPLGetPathSafe(exe_path).c_str());
72
82
    }
73
82
    CPLSetConfigOption("CPL_TMPDIR", "/tmp");
74
82
    CPLSetConfigOption("DISABLE_OPEN_REAL_NETCDF_FILES", "YES");
75
    // Disable PDF text rendering as fontconfig cannot access its config files
76
82
    CPLSetConfigOption("GDAL_PDF_RENDERING_OPTIONS", "RASTER,VECTOR");
77
    // to avoid timeout in WMS driver
78
82
    CPLSetConfigOption("GDAL_WMS_ABORT_CURL_REQUEST", "YES");
79
82
    CPLSetConfigOption("GDAL_HTTP_TIMEOUT", "1");
80
82
    CPLSetConfigOption("GDAL_HTTP_CONNECTTIMEOUT", "1");
81
82
    CPLSetConfigOption("GDAL_CACHEMAX", "1000");  // Limit to 1 GB
82
#ifdef GTIFF_USE_MMAP
83
    CPLSetConfigOption("GTIFF_USE_MMAP", "YES");
84
#endif
85
86
82
#ifdef GDAL_SKIP
87
82
    CPLSetConfigOption("GDAL_SKIP", GDAL_SKIP);
88
82
#endif
89
82
    REGISTER_FUNC();
90
91
82
    return 0;
92
82
}
LLVMFuzzerInitialize
Line
Count
Source
67
82
{
68
82
    const char *exe_path = (*argv)[0];
69
82
    if (CPLGetConfigOption("GDAL_DATA", nullptr) == nullptr)
70
82
    {
71
82
        CPLSetConfigOption("GDAL_DATA", CPLGetPathSafe(exe_path).c_str());
72
82
    }
73
82
    CPLSetConfigOption("CPL_TMPDIR", "/tmp");
74
82
    CPLSetConfigOption("DISABLE_OPEN_REAL_NETCDF_FILES", "YES");
75
    // Disable PDF text rendering as fontconfig cannot access its config files
76
82
    CPLSetConfigOption("GDAL_PDF_RENDERING_OPTIONS", "RASTER,VECTOR");
77
    // to avoid timeout in WMS driver
78
82
    CPLSetConfigOption("GDAL_WMS_ABORT_CURL_REQUEST", "YES");
79
82
    CPLSetConfigOption("GDAL_HTTP_TIMEOUT", "1");
80
82
    CPLSetConfigOption("GDAL_HTTP_CONNECTTIMEOUT", "1");
81
82
    CPLSetConfigOption("GDAL_CACHEMAX", "1000");  // Limit to 1 GB
82
#ifdef GTIFF_USE_MMAP
83
    CPLSetConfigOption("GTIFF_USE_MMAP", "YES");
84
#endif
85
86
82
#ifdef GDAL_SKIP
87
82
    CPLSetConfigOption("GDAL_SKIP", GDAL_SKIP);
88
82
#endif
89
82
    REGISTER_FUNC();
90
91
82
    return 0;
92
82
}
93
94
static void ExploreAttributes(const GDALIHasAttribute *attributeHolder)
95
172k
{
96
172k
    const auto attributes = attributeHolder->GetAttributes();
97
172k
    for (const auto &attribute : attributes)
98
467k
    {
99
467k
        attribute->ReadAsRaw();
100
467k
    }
101
102
172k
    attributeHolder->GetAttribute("i_do_not_exist");
103
172k
}
104
105
static void ExploreArray(const std::shared_ptr<GDALMDArray> &poArray,
106
                         const char *pszDriverName)
107
85.3k
{
108
85.3k
    ExploreAttributes(poArray.get());
109
110
85.3k
    poArray->GetFilename();
111
85.3k
    poArray->GetStructuralInfo();
112
85.3k
    poArray->GetUnit();
113
85.3k
    poArray->GetSpatialRef();
114
85.3k
    poArray->GetRawNoDataValue();
115
85.3k
    poArray->GetOffset();
116
85.3k
    poArray->GetScale();
117
85.3k
    poArray->GetCoordinateVariables();
118
119
85.3k
    const auto nDimCount = poArray->GetDimensionCount();
120
85.3k
    bool bRead = true;
121
85.3k
    constexpr size_t MAX_ALLOC = 1000 * 1000 * 1000U;
122
85.3k
    if (pszDriverName && EQUAL(pszDriverName, "GRIB"))
123
60.5k
    {
124
60.5k
        const auto &poDims = poArray->GetDimensions();
125
60.5k
        if (nDimCount >= 2 &&
126
60.5k
            poDims[nDimCount - 2]->GetSize() >
127
45.8k
                MAX_ALLOC / sizeof(double) / poDims[nDimCount - 1]->GetSize())
128
8.26k
        {
129
8.26k
            bRead = false;
130
8.26k
        }
131
60.5k
    }
132
24.8k
    else
133
24.8k
    {
134
24.8k
        const auto anBlockSize = poArray->GetBlockSize();
135
24.8k
        size_t nBlockSize = poArray->GetDataType().GetSize();
136
24.8k
        for (const auto nDimBlockSize : anBlockSize)
137
36.0k
        {
138
36.0k
            if (nDimBlockSize == 0)
139
3.62k
            {
140
3.62k
                break;
141
3.62k
            }
142
32.4k
            if (nBlockSize > MAX_ALLOC / nDimBlockSize)
143
238
            {
144
238
                bRead = false;
145
238
                break;
146
238
            }
147
32.1k
            nBlockSize *= static_cast<size_t>(nDimBlockSize);
148
32.1k
        }
149
24.8k
    }
150
151
85.3k
    if (bRead && poArray->GetDataType().GetClass() == GEDTC_NUMERIC)
152
74.7k
    {
153
74.7k
        std::vector<GUInt64> anArrayStartIdx(nDimCount);
154
74.7k
        std::vector<size_t> anCount(nDimCount, 1);
155
74.7k
        std::vector<GInt64> anArrayStep(nDimCount);
156
74.7k
        std::vector<GPtrDiff_t> anBufferStride(nDimCount);
157
74.7k
        std::vector<GByte> abyData(poArray->GetDataType().GetSize());
158
74.7k
        poArray->Read(anArrayStartIdx.data(), anCount.data(),
159
74.7k
                      anArrayStep.data(), anBufferStride.data(),
160
74.7k
                      poArray->GetDataType(), &abyData[0]);
161
74.7k
    }
162
85.3k
}
163
164
static void ExploreGroup(const std::shared_ptr<GDALGroup> &poGroup,
165
                         const char *pszDriverName)
166
87.3k
{
167
87.3k
    ExploreAttributes(poGroup.get());
168
169
87.3k
    const auto groupNames = poGroup->GetGroupNames();
170
87.3k
    poGroup->OpenGroup("i_do_not_exist");
171
87.3k
    for (const auto &name : groupNames)
172
78.0k
    {
173
78.0k
        auto poSubGroup = poGroup->OpenGroup(name);
174
78.0k
        if (poSubGroup)
175
72.9k
            ExploreGroup(poSubGroup, pszDriverName);
176
78.0k
    }
177
178
87.3k
    const auto arrayNames = poGroup->GetMDArrayNames();
179
87.3k
    poGroup->OpenMDArray("i_do_not_exist");
180
87.3k
    for (const auto &name : arrayNames)
181
141k
    {
182
141k
        auto poArray = poGroup->OpenMDArray(name);
183
141k
        if (poArray)
184
85.3k
        {
185
85.3k
            ExploreArray(poArray, pszDriverName);
186
85.3k
        }
187
141k
    }
188
87.3k
}
189
190
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
191
449k
{
192
#ifdef USE_FILESYSTEM
193
    char szTempFilename[64];
194
    snprintf(szTempFilename, sizeof(szTempFilename), "/tmp/gdal_fuzzer_%d.%s",
195
2.33k
             (int)getpid(), EXTENSION);
196
    VSILFILE *fp = VSIFOpenL(szTempFilename, "wb");
197
2.33k
    if (!fp)
198
0
    {
199
0
        fprintf(stderr, "Cannot create %s\n", szTempFilename);
200
0
        return 1;
201
0
    }
202
2.33k
    VSIFWriteL(buf, 1, len, fp);
203
#else
204
    VSILFILE *fp = VSIFileFromMemBuffer(
205
223k
        MEM_FILENAME, reinterpret_cast<GByte *>(const_cast<uint8_t *>(buf)),
206
447k
        len, FALSE);
207
#endif
208
2.33k
    VSIFCloseL(fp);
209
210
2.33k
    CPLPushErrorHandler(CPLQuietErrorHandler);
211
#ifdef USE_FILESYSTEM
212
    const char *pszGDALFilename = szTempFilename;
213
#else
214
223k
    const char *pszGDALFilename = GDAL_FILENAME;
215
#endif
216
217
#ifdef DRIVER_NAME
218
    const char *const apszAllowedDrivers[] = {DRIVER_NAME, nullptr};
219
#else
220
2.33k
    const char *const *apszAllowedDrivers = nullptr;
221
2.33k
#endif
222
223
449k
    GDALDatasetH hDS = GDALOpenEx(pszGDALFilename, GDAL_OF_RASTER,
224
2.33k
                                  apszAllowedDrivers, nullptr, nullptr);
225
449k
    if (hDS)
226
367k
    {
227
367k
        const int nTotalBands = GDALGetRasterCount(hDS);
228
367k
        const int nBands = std::min(10, nTotalBands);
229
367k
        bool bDoCheckSum = true;
230
367k
        int nXSizeToRead = std::min(1024, GDALGetRasterXSize(hDS));
231
367k
        int nYSizeToRead = std::min(1024, GDALGetRasterYSize(hDS));
232
367k
        if (nBands > 0)
233
354k
        {
234
354k
            const char *pszInterleave =
235
354k
                GDALGetMetadataItem(hDS, "INTERLEAVE", "IMAGE_STRUCTURE");
236
354k
            int nSimultaneousBands =
237
354k
                (pszInterleave && EQUAL(pszInterleave, "PIXEL")) ? nTotalBands
238
354k
                                                                 : 1;
239
240
            // When using the RGBA interface in pixel-interleaved mode, take
241
            // into account the raw number of bands to compute memory
242
            // requirements
243
354k
            if (nBands == 4 && nSimultaneousBands != 1 &&
244
354k
                GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
245
6.72k
            {
246
6.72k
                GDALDatasetH hRawDS = GDALOpen(
247
6.72k
                    (CPLString("GTIFF_RAW:") + pszGDALFilename).c_str(),
248
6.72k
                    GA_ReadOnly);
249
6.72k
                if (hRawDS)
250
6.57k
                {
251
6.57k
                    nSimultaneousBands = GDALGetRasterCount(hRawDS);
252
                    // shouldn't happen, but will make Coverity Scan happy
253
6.57k
                    if (nSimultaneousBands == 0)
254
0
                        nSimultaneousBands = 1;
255
6.57k
                    GDALClose(hRawDS);
256
6.57k
                }
257
6.72k
            }
258
259
            // If we know that we will need to allocate a lot of memory
260
            // given the block size and interleaving mode, do not read
261
            // pixels to avoid out of memory conditions by ASAN
262
354k
            GIntBig nPixels = 0;
263
1.29M
            for (int i = 0; i < nBands; i++)
264
949k
            {
265
949k
                int nBXSize = 0, nBYSize = 0;
266
949k
                GDALGetBlockSize(GDALGetRasterBand(hDS, i + 1), &nBXSize,
267
949k
                                 &nBYSize);
268
949k
                if (nBXSize == 0 || nBYSize == 0 || nBXSize > INT_MAX / nBYSize)
269
7.94k
                {
270
7.94k
                    bDoCheckSum = false;
271
7.94k
                    break;
272
7.94k
                }
273
274
                // Limit to 1000 blocks read for each band.
275
1.01M
                while ((nXSizeToRead > 1 || nYSizeToRead > 1) &&
276
1.01M
                       (DIV_ROUND_UP(nXSizeToRead, nBXSize) *
277
982k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize) >
278
982k
                        1000))
279
69.4k
                {
280
69.4k
                    if (nXSizeToRead > 1 &&
281
69.4k
                        DIV_ROUND_UP(nXSizeToRead, nBXSize) >
282
58.4k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize))
283
8.08k
                        nXSizeToRead /= 2;
284
61.3k
                    else if (nYSizeToRead > 1)
285
61.3k
                        nYSizeToRead /= 2;
286
0
                    else
287
0
                        nXSizeToRead /= 2;
288
69.4k
                }
289
290
                // Currently decoding of PIXARLOG compressed TIFF requires
291
                // a temporary buffer for the whole strip (if stripped) or
292
                // image (if tiled), so be careful for a
293
                // GTiffSplitBand
294
                // Could probably be fixed for the CHUNKY_STRIP_READ_SUPPORT
295
                // mode.
296
                // Workaround
297
                // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2606
298
941k
                const char *pszCompress =
299
941k
                    GDALGetMetadataItem(hDS, "COMPRESSION", "IMAGE_STRUCTURE");
300
941k
                if (pszCompress != nullptr &&
301
941k
                    ((nBYSize == 1 && GDALGetRasterYSize(hDS) > 1 &&
302
273k
                      GDALGetMetadataItem(GDALGetRasterBand(hDS, 1),
303
45.0k
                                          "BLOCK_OFFSET_0_1",
304
45.0k
                                          "TIFF") == nullptr) ||
305
273k
                     nBXSize != GDALGetRasterXSize(hDS)) &&
306
941k
                    GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
307
69.5k
                {
308
69.5k
                    if (EQUAL(pszCompress, "PIXARLOG") &&
309
69.5k
                        GDALGetRasterYSize(hDS) >
310
6.26k
                            (INT_MAX / 2) / static_cast<int>(sizeof(GUInt16)) /
311
6.26k
                                nSimultaneousBands / GDALGetRasterXSize(hDS))
312
3.60k
                    {
313
3.60k
                        bDoCheckSum = false;
314
3.60k
                    }
315
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2874
316
65.9k
                    else if (EQUAL(pszCompress, "SGILOG24") &&
317
65.9k
                             GDALGetRasterYSize(hDS) >
318
1.37k
                                 (INT_MAX / 2) /
319
1.37k
                                     static_cast<int>(sizeof(GUInt32)) /
320
1.37k
                                     nSimultaneousBands /
321
1.37k
                                     GDALGetRasterXSize(hDS))
322
142
                    {
323
142
                        bDoCheckSum = false;
324
142
                    }
325
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38051
326
65.8k
                    else if (STARTS_WITH_CI(pszCompress, "LERC") &&
327
65.8k
                             (GDALGetRasterYSize(hDS) >
328
2.87k
                                  (INT_MAX / 2) / nSimultaneousBands /
329
2.87k
                                      GDALGetRasterXSize(hDS) ||
330
2.87k
                              static_cast<int64_t>(GDALGetRasterYSize(hDS)) *
331
2.63k
                                          nSimultaneousBands *
332
2.63k
                                          GDALGetRasterXSize(hDS) * 4 / 3 +
333
2.63k
                                      100 >
334
2.63k
                                  (INT_MAX / 2)))
335
334
                    {
336
334
                        bDoCheckSum = false;
337
334
                    }
338
69.5k
                }
339
340
941k
                GIntBig nNewPixels = static_cast<GIntBig>(nBXSize) * nBYSize;
341
941k
                nNewPixels *= DIV_ROUND_UP(nXSizeToRead, nBXSize);
342
941k
                nNewPixels *= DIV_ROUND_UP(nYSizeToRead, nBYSize);
343
941k
                if (nNewPixels > nPixels)
344
346k
                    nPixels = nNewPixels;
345
941k
            }
346
354k
            if (bDoCheckSum)
347
346k
            {
348
346k
                const GDALDataType eDT =
349
346k
                    GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
350
346k
                const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
351
346k
                if (nPixels > 10 * 1024 * 1024 / nDTSize / nSimultaneousBands)
352
30.2k
                {
353
30.2k
                    bDoCheckSum = false;
354
30.2k
                }
355
346k
            }
356
354k
        }
357
367k
        if (bDoCheckSum)
358
328k
        {
359
1.19M
            for (int i = 0; i < nBands; i++)
360
862k
            {
361
862k
                GDALRasterBandH hBand = GDALGetRasterBand(hDS, i + 1);
362
862k
                CPLDebug("FUZZER", "Checksum band %d: %d,%d,%d,%d", i + 1, 0, 0,
363
862k
                         nXSizeToRead, nYSizeToRead);
364
862k
                GDALChecksumImage(hBand, 0, 0, nXSizeToRead, nYSizeToRead);
365
862k
            }
366
328k
        }
367
368
        // Test other API
369
367k
        GDALGetProjectionRef(hDS);
370
367k
        double adfGeoTransform[6];
371
367k
        GDALGetGeoTransform(hDS, adfGeoTransform);
372
367k
        CSLDestroy(GDALGetFileList(hDS));
373
367k
        GDALGetGCPCount(hDS);
374
367k
        GDALGetGCPs(hDS);
375
367k
        GDALGetGCPProjection(hDS);
376
367k
        GDALGetMetadata(hDS, nullptr);
377
367k
        GDALGetMetadataItem(hDS, "foo", nullptr);
378
367k
        CSLDestroy(GDALGetFileList(hDS));
379
367k
        if (nBands > 0)
380
354k
        {
381
354k
            GDALRasterBandH hBand = GDALGetRasterBand(hDS, 1);
382
383
354k
            int bFound = FALSE;
384
354k
            GDALGetRasterNoDataValue(hBand, &bFound);
385
354k
            GDALGetRasterOffset(hBand, &bFound);
386
354k
            GDALGetRasterScale(hBand, &bFound);
387
354k
            GDALGetRasterUnitType(hBand);
388
354k
            GDALGetMetadata(hBand, nullptr);
389
354k
            GDALGetMetadataItem(hBand, "foo", nullptr);
390
391
354k
            int nFlags = GDALGetMaskFlags(hBand);
392
354k
            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand);
393
354k
            GDALGetRasterBandXSize(hMaskBand);
394
354k
            if (bDoCheckSum && nFlags == GMF_PER_DATASET)
395
831
            {
396
831
                int nBXSize = 0, nBYSize = 0;
397
831
                GDALGetBlockSize(hMaskBand, &nBXSize, &nBYSize);
398
831
                if (nBXSize == 0 || nBYSize == 0 ||
399
831
                    nBXSize > INT_MAX / 2 / nBYSize)
400
12
                {
401
                    // do nothing
402
12
                }
403
819
                else
404
819
                {
405
819
                    GDALChecksumImage(hMaskBand, 0, 0, nXSizeToRead,
406
819
                                      nYSizeToRead);
407
819
                }
408
831
            }
409
410
354k
            int nOverviewCount = GDALGetOverviewCount(hBand);
411
435k
            for (int i = 0; i < nOverviewCount; i++)
412
81.0k
            {
413
81.0k
                GDALGetOverview(hBand, i);
414
81.0k
            }
415
354k
        }
416
417
367k
        GDALClose(hDS);
418
367k
    }
419
420
2.33k
    auto poDS = std::unique_ptr<GDALDataset>(
421
449k
        GDALDataset::Open(pszGDALFilename, GDAL_OF_MULTIDIM_RASTER));
422
449k
    if (poDS)
423
28.4k
    {
424
28.4k
        auto poDriver = poDS->GetDriver();
425
28.4k
        const char *pszDriverName = nullptr;
426
28.4k
        if (poDriver)
427
28.4k
            pszDriverName = poDriver->GetDescription();
428
28.4k
        auto poRootGroup = poDS->GetRootGroup();
429
28.4k
        poDS.reset();
430
28.4k
        if (poRootGroup)
431
28.4k
            ExploreGroup(poRootGroup, pszDriverName);
432
28.4k
    }
433
434
2.33k
    CPLPopErrorHandler();
435
#ifdef USE_FILESYSTEM
436
    VSIUnlink(szTempFilename);
437
#else
438
223k
    VSIUnlink(MEM_FILENAME);
439
#endif
440
2.33k
    return 0;
441
449k
}
LLVMFuzzerTestOneInput
Line
Count
Source
191
223k
{
192
#ifdef USE_FILESYSTEM
193
    char szTempFilename[64];
194
    snprintf(szTempFilename, sizeof(szTempFilename), "/tmp/gdal_fuzzer_%d.%s",
195
             (int)getpid(), EXTENSION);
196
    VSILFILE *fp = VSIFOpenL(szTempFilename, "wb");
197
    if (!fp)
198
    {
199
        fprintf(stderr, "Cannot create %s\n", szTempFilename);
200
        return 1;
201
    }
202
    VSIFWriteL(buf, 1, len, fp);
203
#else
204
223k
    VSILFILE *fp = VSIFileFromMemBuffer(
205
223k
        MEM_FILENAME, reinterpret_cast<GByte *>(const_cast<uint8_t *>(buf)),
206
223k
        len, FALSE);
207
223k
#endif
208
223k
    VSIFCloseL(fp);
209
210
223k
    CPLPushErrorHandler(CPLQuietErrorHandler);
211
#ifdef USE_FILESYSTEM
212
    const char *pszGDALFilename = szTempFilename;
213
#else
214
223k
    const char *pszGDALFilename = GDAL_FILENAME;
215
223k
#endif
216
217
#ifdef DRIVER_NAME
218
    const char *const apszAllowedDrivers[] = {DRIVER_NAME, nullptr};
219
#else
220
223k
    const char *const *apszAllowedDrivers = nullptr;
221
223k
#endif
222
223
223k
    GDALDatasetH hDS = GDALOpenEx(pszGDALFilename, GDAL_OF_RASTER,
224
223k
                                  apszAllowedDrivers, nullptr, nullptr);
225
223k
    if (hDS)
226
182k
    {
227
182k
        const int nTotalBands = GDALGetRasterCount(hDS);
228
182k
        const int nBands = std::min(10, nTotalBands);
229
182k
        bool bDoCheckSum = true;
230
182k
        int nXSizeToRead = std::min(1024, GDALGetRasterXSize(hDS));
231
182k
        int nYSizeToRead = std::min(1024, GDALGetRasterYSize(hDS));
232
182k
        if (nBands > 0)
233
176k
        {
234
176k
            const char *pszInterleave =
235
176k
                GDALGetMetadataItem(hDS, "INTERLEAVE", "IMAGE_STRUCTURE");
236
176k
            int nSimultaneousBands =
237
176k
                (pszInterleave && EQUAL(pszInterleave, "PIXEL")) ? nTotalBands
238
176k
                                                                 : 1;
239
240
            // When using the RGBA interface in pixel-interleaved mode, take
241
            // into account the raw number of bands to compute memory
242
            // requirements
243
176k
            if (nBands == 4 && nSimultaneousBands != 1 &&
244
176k
                GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
245
3.34k
            {
246
3.34k
                GDALDatasetH hRawDS = GDALOpen(
247
3.34k
                    (CPLString("GTIFF_RAW:") + pszGDALFilename).c_str(),
248
3.34k
                    GA_ReadOnly);
249
3.34k
                if (hRawDS)
250
3.27k
                {
251
3.27k
                    nSimultaneousBands = GDALGetRasterCount(hRawDS);
252
                    // shouldn't happen, but will make Coverity Scan happy
253
3.27k
                    if (nSimultaneousBands == 0)
254
0
                        nSimultaneousBands = 1;
255
3.27k
                    GDALClose(hRawDS);
256
3.27k
                }
257
3.34k
            }
258
259
            // If we know that we will need to allocate a lot of memory
260
            // given the block size and interleaving mode, do not read
261
            // pixels to avoid out of memory conditions by ASAN
262
176k
            GIntBig nPixels = 0;
263
642k
            for (int i = 0; i < nBands; i++)
264
470k
            {
265
470k
                int nBXSize = 0, nBYSize = 0;
266
470k
                GDALGetBlockSize(GDALGetRasterBand(hDS, i + 1), &nBXSize,
267
470k
                                 &nBYSize);
268
470k
                if (nBXSize == 0 || nBYSize == 0 || nBXSize > INT_MAX / nBYSize)
269
3.96k
                {
270
3.96k
                    bDoCheckSum = false;
271
3.96k
                    break;
272
3.96k
                }
273
274
                // Limit to 1000 blocks read for each band.
275
500k
                while ((nXSizeToRead > 1 || nYSizeToRead > 1) &&
276
500k
                       (DIV_ROUND_UP(nXSizeToRead, nBXSize) *
277
486k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize) >
278
486k
                        1000))
279
34.3k
                {
280
34.3k
                    if (nXSizeToRead > 1 &&
281
34.3k
                        DIV_ROUND_UP(nXSizeToRead, nBXSize) >
282
28.8k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize))
283
4.03k
                        nXSizeToRead /= 2;
284
30.3k
                    else if (nYSizeToRead > 1)
285
30.3k
                        nYSizeToRead /= 2;
286
0
                    else
287
0
                        nXSizeToRead /= 2;
288
34.3k
                }
289
290
                // Currently decoding of PIXARLOG compressed TIFF requires
291
                // a temporary buffer for the whole strip (if stripped) or
292
                // image (if tiled), so be careful for a
293
                // GTiffSplitBand
294
                // Could probably be fixed for the CHUNKY_STRIP_READ_SUPPORT
295
                // mode.
296
                // Workaround
297
                // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2606
298
466k
                const char *pszCompress =
299
466k
                    GDALGetMetadataItem(hDS, "COMPRESSION", "IMAGE_STRUCTURE");
300
466k
                if (pszCompress != nullptr &&
301
466k
                    ((nBYSize == 1 && GDALGetRasterYSize(hDS) > 1 &&
302
135k
                      GDALGetMetadataItem(GDALGetRasterBand(hDS, 1),
303
22.2k
                                          "BLOCK_OFFSET_0_1",
304
22.2k
                                          "TIFF") == nullptr) ||
305
135k
                     nBXSize != GDALGetRasterXSize(hDS)) &&
306
466k
                    GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
307
34.5k
                {
308
34.5k
                    if (EQUAL(pszCompress, "PIXARLOG") &&
309
34.5k
                        GDALGetRasterYSize(hDS) >
310
3.13k
                            (INT_MAX / 2) / static_cast<int>(sizeof(GUInt16)) /
311
3.13k
                                nSimultaneousBands / GDALGetRasterXSize(hDS))
312
1.80k
                    {
313
1.80k
                        bDoCheckSum = false;
314
1.80k
                    }
315
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2874
316
32.7k
                    else if (EQUAL(pszCompress, "SGILOG24") &&
317
32.7k
                             GDALGetRasterYSize(hDS) >
318
679
                                 (INT_MAX / 2) /
319
679
                                     static_cast<int>(sizeof(GUInt32)) /
320
679
                                     nSimultaneousBands /
321
679
                                     GDALGetRasterXSize(hDS))
322
71
                    {
323
71
                        bDoCheckSum = false;
324
71
                    }
325
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38051
326
32.6k
                    else if (STARTS_WITH_CI(pszCompress, "LERC") &&
327
32.6k
                             (GDALGetRasterYSize(hDS) >
328
1.43k
                                  (INT_MAX / 2) / nSimultaneousBands /
329
1.43k
                                      GDALGetRasterXSize(hDS) ||
330
1.43k
                              static_cast<int64_t>(GDALGetRasterYSize(hDS)) *
331
1.31k
                                          nSimultaneousBands *
332
1.31k
                                          GDALGetRasterXSize(hDS) * 4 / 3 +
333
1.31k
                                      100 >
334
1.31k
                                  (INT_MAX / 2)))
335
167
                    {
336
167
                        bDoCheckSum = false;
337
167
                    }
338
34.5k
                }
339
340
466k
                GIntBig nNewPixels = static_cast<GIntBig>(nBXSize) * nBYSize;
341
466k
                nNewPixels *= DIV_ROUND_UP(nXSizeToRead, nBXSize);
342
466k
                nNewPixels *= DIV_ROUND_UP(nYSizeToRead, nBYSize);
343
466k
                if (nNewPixels > nPixels)
344
172k
                    nPixels = nNewPixels;
345
466k
            }
346
176k
            if (bDoCheckSum)
347
172k
            {
348
172k
                const GDALDataType eDT =
349
172k
                    GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
350
172k
                const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
351
172k
                if (nPixels > 10 * 1024 * 1024 / nDTSize / nSimultaneousBands)
352
15.1k
                {
353
15.1k
                    bDoCheckSum = false;
354
15.1k
                }
355
172k
            }
356
176k
        }
357
182k
        if (bDoCheckSum)
358
163k
        {
359
590k
            for (int i = 0; i < nBands; i++)
360
427k
            {
361
427k
                GDALRasterBandH hBand = GDALGetRasterBand(hDS, i + 1);
362
427k
                CPLDebug("FUZZER", "Checksum band %d: %d,%d,%d,%d", i + 1, 0, 0,
363
427k
                         nXSizeToRead, nYSizeToRead);
364
427k
                GDALChecksumImage(hBand, 0, 0, nXSizeToRead, nYSizeToRead);
365
427k
            }
366
163k
        }
367
368
        // Test other API
369
182k
        GDALGetProjectionRef(hDS);
370
182k
        double adfGeoTransform[6];
371
182k
        GDALGetGeoTransform(hDS, adfGeoTransform);
372
182k
        CSLDestroy(GDALGetFileList(hDS));
373
182k
        GDALGetGCPCount(hDS);
374
182k
        GDALGetGCPs(hDS);
375
182k
        GDALGetGCPProjection(hDS);
376
182k
        GDALGetMetadata(hDS, nullptr);
377
182k
        GDALGetMetadataItem(hDS, "foo", nullptr);
378
182k
        CSLDestroy(GDALGetFileList(hDS));
379
182k
        if (nBands > 0)
380
176k
        {
381
176k
            GDALRasterBandH hBand = GDALGetRasterBand(hDS, 1);
382
383
176k
            int bFound = FALSE;
384
176k
            GDALGetRasterNoDataValue(hBand, &bFound);
385
176k
            GDALGetRasterOffset(hBand, &bFound);
386
176k
            GDALGetRasterScale(hBand, &bFound);
387
176k
            GDALGetRasterUnitType(hBand);
388
176k
            GDALGetMetadata(hBand, nullptr);
389
176k
            GDALGetMetadataItem(hBand, "foo", nullptr);
390
391
176k
            int nFlags = GDALGetMaskFlags(hBand);
392
176k
            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand);
393
176k
            GDALGetRasterBandXSize(hMaskBand);
394
176k
            if (bDoCheckSum && nFlags == GMF_PER_DATASET)
395
410
            {
396
410
                int nBXSize = 0, nBYSize = 0;
397
410
                GDALGetBlockSize(hMaskBand, &nBXSize, &nBYSize);
398
410
                if (nBXSize == 0 || nBYSize == 0 ||
399
410
                    nBXSize > INT_MAX / 2 / nBYSize)
400
6
                {
401
                    // do nothing
402
6
                }
403
404
                else
404
404
                {
405
404
                    GDALChecksumImage(hMaskBand, 0, 0, nXSizeToRead,
406
404
                                      nYSizeToRead);
407
404
                }
408
410
            }
409
410
176k
            int nOverviewCount = GDALGetOverviewCount(hBand);
411
216k
            for (int i = 0; i < nOverviewCount; i++)
412
39.8k
            {
413
39.8k
                GDALGetOverview(hBand, i);
414
39.8k
            }
415
176k
        }
416
417
182k
        GDALClose(hDS);
418
182k
    }
419
420
223k
    auto poDS = std::unique_ptr<GDALDataset>(
421
223k
        GDALDataset::Open(pszGDALFilename, GDAL_OF_MULTIDIM_RASTER));
422
223k
    if (poDS)
423
13.9k
    {
424
13.9k
        auto poDriver = poDS->GetDriver();
425
13.9k
        const char *pszDriverName = nullptr;
426
13.9k
        if (poDriver)
427
13.9k
            pszDriverName = poDriver->GetDescription();
428
13.9k
        auto poRootGroup = poDS->GetRootGroup();
429
13.9k
        poDS.reset();
430
13.9k
        if (poRootGroup)
431
13.9k
            ExploreGroup(poRootGroup, pszDriverName);
432
13.9k
    }
433
434
223k
    CPLPopErrorHandler();
435
#ifdef USE_FILESYSTEM
436
    VSIUnlink(szTempFilename);
437
#else
438
223k
    VSIUnlink(MEM_FILENAME);
439
223k
#endif
440
223k
    return 0;
441
223k
}
LLVMFuzzerTestOneInput
Line
Count
Source
191
223k
{
192
#ifdef USE_FILESYSTEM
193
    char szTempFilename[64];
194
    snprintf(szTempFilename, sizeof(szTempFilename), "/tmp/gdal_fuzzer_%d.%s",
195
             (int)getpid(), EXTENSION);
196
    VSILFILE *fp = VSIFOpenL(szTempFilename, "wb");
197
    if (!fp)
198
    {
199
        fprintf(stderr, "Cannot create %s\n", szTempFilename);
200
        return 1;
201
    }
202
    VSIFWriteL(buf, 1, len, fp);
203
#else
204
223k
    VSILFILE *fp = VSIFileFromMemBuffer(
205
223k
        MEM_FILENAME, reinterpret_cast<GByte *>(const_cast<uint8_t *>(buf)),
206
223k
        len, FALSE);
207
223k
#endif
208
223k
    VSIFCloseL(fp);
209
210
223k
    CPLPushErrorHandler(CPLQuietErrorHandler);
211
#ifdef USE_FILESYSTEM
212
    const char *pszGDALFilename = szTempFilename;
213
#else
214
223k
    const char *pszGDALFilename = GDAL_FILENAME;
215
223k
#endif
216
217
#ifdef DRIVER_NAME
218
    const char *const apszAllowedDrivers[] = {DRIVER_NAME, nullptr};
219
#else
220
223k
    const char *const *apszAllowedDrivers = nullptr;
221
223k
#endif
222
223
223k
    GDALDatasetH hDS = GDALOpenEx(pszGDALFilename, GDAL_OF_RASTER,
224
223k
                                  apszAllowedDrivers, nullptr, nullptr);
225
223k
    if (hDS)
226
182k
    {
227
182k
        const int nTotalBands = GDALGetRasterCount(hDS);
228
182k
        const int nBands = std::min(10, nTotalBands);
229
182k
        bool bDoCheckSum = true;
230
182k
        int nXSizeToRead = std::min(1024, GDALGetRasterXSize(hDS));
231
182k
        int nYSizeToRead = std::min(1024, GDALGetRasterYSize(hDS));
232
182k
        if (nBands > 0)
233
176k
        {
234
176k
            const char *pszInterleave =
235
176k
                GDALGetMetadataItem(hDS, "INTERLEAVE", "IMAGE_STRUCTURE");
236
176k
            int nSimultaneousBands =
237
176k
                (pszInterleave && EQUAL(pszInterleave, "PIXEL")) ? nTotalBands
238
176k
                                                                 : 1;
239
240
            // When using the RGBA interface in pixel-interleaved mode, take
241
            // into account the raw number of bands to compute memory
242
            // requirements
243
176k
            if (nBands == 4 && nSimultaneousBands != 1 &&
244
176k
                GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
245
3.34k
            {
246
3.34k
                GDALDatasetH hRawDS = GDALOpen(
247
3.34k
                    (CPLString("GTIFF_RAW:") + pszGDALFilename).c_str(),
248
3.34k
                    GA_ReadOnly);
249
3.34k
                if (hRawDS)
250
3.27k
                {
251
3.27k
                    nSimultaneousBands = GDALGetRasterCount(hRawDS);
252
                    // shouldn't happen, but will make Coverity Scan happy
253
3.27k
                    if (nSimultaneousBands == 0)
254
0
                        nSimultaneousBands = 1;
255
3.27k
                    GDALClose(hRawDS);
256
3.27k
                }
257
3.34k
            }
258
259
            // If we know that we will need to allocate a lot of memory
260
            // given the block size and interleaving mode, do not read
261
            // pixels to avoid out of memory conditions by ASAN
262
176k
            GIntBig nPixels = 0;
263
642k
            for (int i = 0; i < nBands; i++)
264
470k
            {
265
470k
                int nBXSize = 0, nBYSize = 0;
266
470k
                GDALGetBlockSize(GDALGetRasterBand(hDS, i + 1), &nBXSize,
267
470k
                                 &nBYSize);
268
470k
                if (nBXSize == 0 || nBYSize == 0 || nBXSize > INT_MAX / nBYSize)
269
3.96k
                {
270
3.96k
                    bDoCheckSum = false;
271
3.96k
                    break;
272
3.96k
                }
273
274
                // Limit to 1000 blocks read for each band.
275
500k
                while ((nXSizeToRead > 1 || nYSizeToRead > 1) &&
276
500k
                       (DIV_ROUND_UP(nXSizeToRead, nBXSize) *
277
486k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize) >
278
486k
                        1000))
279
34.3k
                {
280
34.3k
                    if (nXSizeToRead > 1 &&
281
34.3k
                        DIV_ROUND_UP(nXSizeToRead, nBXSize) >
282
28.8k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize))
283
4.03k
                        nXSizeToRead /= 2;
284
30.3k
                    else if (nYSizeToRead > 1)
285
30.3k
                        nYSizeToRead /= 2;
286
0
                    else
287
0
                        nXSizeToRead /= 2;
288
34.3k
                }
289
290
                // Currently decoding of PIXARLOG compressed TIFF requires
291
                // a temporary buffer for the whole strip (if stripped) or
292
                // image (if tiled), so be careful for a
293
                // GTiffSplitBand
294
                // Could probably be fixed for the CHUNKY_STRIP_READ_SUPPORT
295
                // mode.
296
                // Workaround
297
                // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2606
298
466k
                const char *pszCompress =
299
466k
                    GDALGetMetadataItem(hDS, "COMPRESSION", "IMAGE_STRUCTURE");
300
466k
                if (pszCompress != nullptr &&
301
466k
                    ((nBYSize == 1 && GDALGetRasterYSize(hDS) > 1 &&
302
135k
                      GDALGetMetadataItem(GDALGetRasterBand(hDS, 1),
303
22.2k
                                          "BLOCK_OFFSET_0_1",
304
22.2k
                                          "TIFF") == nullptr) ||
305
135k
                     nBXSize != GDALGetRasterXSize(hDS)) &&
306
466k
                    GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
307
34.5k
                {
308
34.5k
                    if (EQUAL(pszCompress, "PIXARLOG") &&
309
34.5k
                        GDALGetRasterYSize(hDS) >
310
3.13k
                            (INT_MAX / 2) / static_cast<int>(sizeof(GUInt16)) /
311
3.13k
                                nSimultaneousBands / GDALGetRasterXSize(hDS))
312
1.80k
                    {
313
1.80k
                        bDoCheckSum = false;
314
1.80k
                    }
315
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2874
316
32.7k
                    else if (EQUAL(pszCompress, "SGILOG24") &&
317
32.7k
                             GDALGetRasterYSize(hDS) >
318
679
                                 (INT_MAX / 2) /
319
679
                                     static_cast<int>(sizeof(GUInt32)) /
320
679
                                     nSimultaneousBands /
321
679
                                     GDALGetRasterXSize(hDS))
322
71
                    {
323
71
                        bDoCheckSum = false;
324
71
                    }
325
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38051
326
32.6k
                    else if (STARTS_WITH_CI(pszCompress, "LERC") &&
327
32.6k
                             (GDALGetRasterYSize(hDS) >
328
1.43k
                                  (INT_MAX / 2) / nSimultaneousBands /
329
1.43k
                                      GDALGetRasterXSize(hDS) ||
330
1.43k
                              static_cast<int64_t>(GDALGetRasterYSize(hDS)) *
331
1.31k
                                          nSimultaneousBands *
332
1.31k
                                          GDALGetRasterXSize(hDS) * 4 / 3 +
333
1.31k
                                      100 >
334
1.31k
                                  (INT_MAX / 2)))
335
167
                    {
336
167
                        bDoCheckSum = false;
337
167
                    }
338
34.5k
                }
339
340
466k
                GIntBig nNewPixels = static_cast<GIntBig>(nBXSize) * nBYSize;
341
466k
                nNewPixels *= DIV_ROUND_UP(nXSizeToRead, nBXSize);
342
466k
                nNewPixels *= DIV_ROUND_UP(nYSizeToRead, nBYSize);
343
466k
                if (nNewPixels > nPixels)
344
172k
                    nPixels = nNewPixels;
345
466k
            }
346
176k
            if (bDoCheckSum)
347
172k
            {
348
172k
                const GDALDataType eDT =
349
172k
                    GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
350
172k
                const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
351
172k
                if (nPixels > 10 * 1024 * 1024 / nDTSize / nSimultaneousBands)
352
15.1k
                {
353
15.1k
                    bDoCheckSum = false;
354
15.1k
                }
355
172k
            }
356
176k
        }
357
182k
        if (bDoCheckSum)
358
163k
        {
359
590k
            for (int i = 0; i < nBands; i++)
360
427k
            {
361
427k
                GDALRasterBandH hBand = GDALGetRasterBand(hDS, i + 1);
362
427k
                CPLDebug("FUZZER", "Checksum band %d: %d,%d,%d,%d", i + 1, 0, 0,
363
427k
                         nXSizeToRead, nYSizeToRead);
364
427k
                GDALChecksumImage(hBand, 0, 0, nXSizeToRead, nYSizeToRead);
365
427k
            }
366
163k
        }
367
368
        // Test other API
369
182k
        GDALGetProjectionRef(hDS);
370
182k
        double adfGeoTransform[6];
371
182k
        GDALGetGeoTransform(hDS, adfGeoTransform);
372
182k
        CSLDestroy(GDALGetFileList(hDS));
373
182k
        GDALGetGCPCount(hDS);
374
182k
        GDALGetGCPs(hDS);
375
182k
        GDALGetGCPProjection(hDS);
376
182k
        GDALGetMetadata(hDS, nullptr);
377
182k
        GDALGetMetadataItem(hDS, "foo", nullptr);
378
182k
        CSLDestroy(GDALGetFileList(hDS));
379
182k
        if (nBands > 0)
380
176k
        {
381
176k
            GDALRasterBandH hBand = GDALGetRasterBand(hDS, 1);
382
383
176k
            int bFound = FALSE;
384
176k
            GDALGetRasterNoDataValue(hBand, &bFound);
385
176k
            GDALGetRasterOffset(hBand, &bFound);
386
176k
            GDALGetRasterScale(hBand, &bFound);
387
176k
            GDALGetRasterUnitType(hBand);
388
176k
            GDALGetMetadata(hBand, nullptr);
389
176k
            GDALGetMetadataItem(hBand, "foo", nullptr);
390
391
176k
            int nFlags = GDALGetMaskFlags(hBand);
392
176k
            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand);
393
176k
            GDALGetRasterBandXSize(hMaskBand);
394
176k
            if (bDoCheckSum && nFlags == GMF_PER_DATASET)
395
410
            {
396
410
                int nBXSize = 0, nBYSize = 0;
397
410
                GDALGetBlockSize(hMaskBand, &nBXSize, &nBYSize);
398
410
                if (nBXSize == 0 || nBYSize == 0 ||
399
410
                    nBXSize > INT_MAX / 2 / nBYSize)
400
6
                {
401
                    // do nothing
402
6
                }
403
404
                else
404
404
                {
405
404
                    GDALChecksumImage(hMaskBand, 0, 0, nXSizeToRead,
406
404
                                      nYSizeToRead);
407
404
                }
408
410
            }
409
410
176k
            int nOverviewCount = GDALGetOverviewCount(hBand);
411
216k
            for (int i = 0; i < nOverviewCount; i++)
412
39.8k
            {
413
39.8k
                GDALGetOverview(hBand, i);
414
39.8k
            }
415
176k
        }
416
417
182k
        GDALClose(hDS);
418
182k
    }
419
420
223k
    auto poDS = std::unique_ptr<GDALDataset>(
421
223k
        GDALDataset::Open(pszGDALFilename, GDAL_OF_MULTIDIM_RASTER));
422
223k
    if (poDS)
423
13.9k
    {
424
13.9k
        auto poDriver = poDS->GetDriver();
425
13.9k
        const char *pszDriverName = nullptr;
426
13.9k
        if (poDriver)
427
13.9k
            pszDriverName = poDriver->GetDescription();
428
13.9k
        auto poRootGroup = poDS->GetRootGroup();
429
13.9k
        poDS.reset();
430
13.9k
        if (poRootGroup)
431
13.9k
            ExploreGroup(poRootGroup, pszDriverName);
432
13.9k
    }
433
434
223k
    CPLPopErrorHandler();
435
#ifdef USE_FILESYSTEM
436
    VSIUnlink(szTempFilename);
437
#else
438
223k
    VSIUnlink(MEM_FILENAME);
439
223k
#endif
440
223k
    return 0;
441
223k
}
LLVMFuzzerTestOneInput
Line
Count
Source
191
2.33k
{
192
2.33k
#ifdef USE_FILESYSTEM
193
2.33k
    char szTempFilename[64];
194
2.33k
    snprintf(szTempFilename, sizeof(szTempFilename), "/tmp/gdal_fuzzer_%d.%s",
195
2.33k
             (int)getpid(), EXTENSION);
196
2.33k
    VSILFILE *fp = VSIFOpenL(szTempFilename, "wb");
197
2.33k
    if (!fp)
198
0
    {
199
0
        fprintf(stderr, "Cannot create %s\n", szTempFilename);
200
0
        return 1;
201
0
    }
202
2.33k
    VSIFWriteL(buf, 1, len, fp);
203
#else
204
    VSILFILE *fp = VSIFileFromMemBuffer(
205
        MEM_FILENAME, reinterpret_cast<GByte *>(const_cast<uint8_t *>(buf)),
206
        len, FALSE);
207
#endif
208
2.33k
    VSIFCloseL(fp);
209
210
2.33k
    CPLPushErrorHandler(CPLQuietErrorHandler);
211
2.33k
#ifdef USE_FILESYSTEM
212
2.33k
    const char *pszGDALFilename = szTempFilename;
213
#else
214
    const char *pszGDALFilename = GDAL_FILENAME;
215
#endif
216
217
#ifdef DRIVER_NAME
218
    const char *const apszAllowedDrivers[] = {DRIVER_NAME, nullptr};
219
#else
220
2.33k
    const char *const *apszAllowedDrivers = nullptr;
221
2.33k
#endif
222
223
2.33k
    GDALDatasetH hDS = GDALOpenEx(pszGDALFilename, GDAL_OF_RASTER,
224
2.33k
                                  apszAllowedDrivers, nullptr, nullptr);
225
2.33k
    if (hDS)
226
1.91k
    {
227
1.91k
        const int nTotalBands = GDALGetRasterCount(hDS);
228
1.91k
        const int nBands = std::min(10, nTotalBands);
229
1.91k
        bool bDoCheckSum = true;
230
1.91k
        int nXSizeToRead = std::min(1024, GDALGetRasterXSize(hDS));
231
1.91k
        int nYSizeToRead = std::min(1024, GDALGetRasterYSize(hDS));
232
1.91k
        if (nBands > 0)
233
1.87k
        {
234
1.87k
            const char *pszInterleave =
235
1.87k
                GDALGetMetadataItem(hDS, "INTERLEAVE", "IMAGE_STRUCTURE");
236
1.87k
            int nSimultaneousBands =
237
1.87k
                (pszInterleave && EQUAL(pszInterleave, "PIXEL")) ? nTotalBands
238
1.87k
                                                                 : 1;
239
240
            // When using the RGBA interface in pixel-interleaved mode, take
241
            // into account the raw number of bands to compute memory
242
            // requirements
243
1.87k
            if (nBands == 4 && nSimultaneousBands != 1 &&
244
1.87k
                GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
245
29
            {
246
29
                GDALDatasetH hRawDS = GDALOpen(
247
29
                    (CPLString("GTIFF_RAW:") + pszGDALFilename).c_str(),
248
29
                    GA_ReadOnly);
249
29
                if (hRawDS)
250
29
                {
251
29
                    nSimultaneousBands = GDALGetRasterCount(hRawDS);
252
                    // shouldn't happen, but will make Coverity Scan happy
253
29
                    if (nSimultaneousBands == 0)
254
0
                        nSimultaneousBands = 1;
255
29
                    GDALClose(hRawDS);
256
29
                }
257
29
            }
258
259
            // If we know that we will need to allocate a lot of memory
260
            // given the block size and interleaving mode, do not read
261
            // pixels to avoid out of memory conditions by ASAN
262
1.87k
            GIntBig nPixels = 0;
263
10.4k
            for (int i = 0; i < nBands; i++)
264
8.61k
            {
265
8.61k
                int nBXSize = 0, nBYSize = 0;
266
8.61k
                GDALGetBlockSize(GDALGetRasterBand(hDS, i + 1), &nBXSize,
267
8.61k
                                 &nBYSize);
268
8.61k
                if (nBXSize == 0 || nBYSize == 0 || nBXSize > INT_MAX / nBYSize)
269
10
                {
270
10
                    bDoCheckSum = false;
271
10
                    break;
272
10
                }
273
274
                // Limit to 1000 blocks read for each band.
275
9.32k
                while ((nXSizeToRead > 1 || nYSizeToRead > 1) &&
276
9.32k
                       (DIV_ROUND_UP(nXSizeToRead, nBXSize) *
277
9.30k
                            DIV_ROUND_UP(nYSizeToRead, nBYSize) >
278
9.30k
                        1000))
279
715
                {
280
715
                    if (nXSizeToRead > 1 &&
281
715
                        DIV_ROUND_UP(nXSizeToRead, nBXSize) >
282
709
                            DIV_ROUND_UP(nYSizeToRead, nBYSize))
283
12
                        nXSizeToRead /= 2;
284
703
                    else if (nYSizeToRead > 1)
285
703
                        nYSizeToRead /= 2;
286
0
                    else
287
0
                        nXSizeToRead /= 2;
288
715
                }
289
290
                // Currently decoding of PIXARLOG compressed TIFF requires
291
                // a temporary buffer for the whole strip (if stripped) or
292
                // image (if tiled), so be careful for a
293
                // GTiffSplitBand
294
                // Could probably be fixed for the CHUNKY_STRIP_READ_SUPPORT
295
                // mode.
296
                // Workaround
297
                // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2606
298
8.60k
                const char *pszCompress =
299
8.60k
                    GDALGetMetadataItem(hDS, "COMPRESSION", "IMAGE_STRUCTURE");
300
8.60k
                if (pszCompress != nullptr &&
301
8.60k
                    ((nBYSize == 1 && GDALGetRasterYSize(hDS) > 1 &&
302
1.51k
                      GDALGetMetadataItem(GDALGetRasterBand(hDS, 1),
303
635
                                          "BLOCK_OFFSET_0_1",
304
635
                                          "TIFF") == nullptr) ||
305
1.51k
                     nBXSize != GDALGetRasterXSize(hDS)) &&
306
8.60k
                    GDALGetDatasetDriver(hDS) == GDALGetDriverByName("GTiff"))
307
511
                {
308
511
                    if (EQUAL(pszCompress, "PIXARLOG") &&
309
511
                        GDALGetRasterYSize(hDS) >
310
0
                            (INT_MAX / 2) / static_cast<int>(sizeof(GUInt16)) /
311
0
                                nSimultaneousBands / GDALGetRasterXSize(hDS))
312
0
                    {
313
0
                        bDoCheckSum = false;
314
0
                    }
315
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2874
316
511
                    else if (EQUAL(pszCompress, "SGILOG24") &&
317
511
                             GDALGetRasterYSize(hDS) >
318
12
                                 (INT_MAX / 2) /
319
12
                                     static_cast<int>(sizeof(GUInt32)) /
320
12
                                     nSimultaneousBands /
321
12
                                     GDALGetRasterXSize(hDS))
322
0
                    {
323
0
                        bDoCheckSum = false;
324
0
                    }
325
                    // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38051
326
511
                    else if (STARTS_WITH_CI(pszCompress, "LERC") &&
327
511
                             (GDALGetRasterYSize(hDS) >
328
11
                                  (INT_MAX / 2) / nSimultaneousBands /
329
11
                                      GDALGetRasterXSize(hDS) ||
330
11
                              static_cast<int64_t>(GDALGetRasterYSize(hDS)) *
331
11
                                          nSimultaneousBands *
332
11
                                          GDALGetRasterXSize(hDS) * 4 / 3 +
333
11
                                      100 >
334
11
                                  (INT_MAX / 2)))
335
0
                    {
336
0
                        bDoCheckSum = false;
337
0
                    }
338
511
                }
339
340
8.60k
                GIntBig nNewPixels = static_cast<GIntBig>(nBXSize) * nBYSize;
341
8.60k
                nNewPixels *= DIV_ROUND_UP(nXSizeToRead, nBXSize);
342
8.60k
                nNewPixels *= DIV_ROUND_UP(nYSizeToRead, nBYSize);
343
8.60k
                if (nNewPixels > nPixels)
344
1.86k
                    nPixels = nNewPixels;
345
8.60k
            }
346
1.87k
            if (bDoCheckSum)
347
1.86k
            {
348
1.86k
                const GDALDataType eDT =
349
1.86k
                    GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
350
1.86k
                const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
351
1.86k
                if (nPixels > 10 * 1024 * 1024 / nDTSize / nSimultaneousBands)
352
48
                {
353
48
                    bDoCheckSum = false;
354
48
                }
355
1.86k
            }
356
1.87k
        }
357
1.91k
        if (bDoCheckSum)
358
1.85k
        {
359
10.1k
            for (int i = 0; i < nBands; i++)
360
8.31k
            {
361
8.31k
                GDALRasterBandH hBand = GDALGetRasterBand(hDS, i + 1);
362
8.31k
                CPLDebug("FUZZER", "Checksum band %d: %d,%d,%d,%d", i + 1, 0, 0,
363
8.31k
                         nXSizeToRead, nYSizeToRead);
364
8.31k
                GDALChecksumImage(hBand, 0, 0, nXSizeToRead, nYSizeToRead);
365
8.31k
            }
366
1.85k
        }
367
368
        // Test other API
369
1.91k
        GDALGetProjectionRef(hDS);
370
1.91k
        double adfGeoTransform[6];
371
1.91k
        GDALGetGeoTransform(hDS, adfGeoTransform);
372
1.91k
        CSLDestroy(GDALGetFileList(hDS));
373
1.91k
        GDALGetGCPCount(hDS);
374
1.91k
        GDALGetGCPs(hDS);
375
1.91k
        GDALGetGCPProjection(hDS);
376
1.91k
        GDALGetMetadata(hDS, nullptr);
377
1.91k
        GDALGetMetadataItem(hDS, "foo", nullptr);
378
1.91k
        CSLDestroy(GDALGetFileList(hDS));
379
1.91k
        if (nBands > 0)
380
1.87k
        {
381
1.87k
            GDALRasterBandH hBand = GDALGetRasterBand(hDS, 1);
382
383
1.87k
            int bFound = FALSE;
384
1.87k
            GDALGetRasterNoDataValue(hBand, &bFound);
385
1.87k
            GDALGetRasterOffset(hBand, &bFound);
386
1.87k
            GDALGetRasterScale(hBand, &bFound);
387
1.87k
            GDALGetRasterUnitType(hBand);
388
1.87k
            GDALGetMetadata(hBand, nullptr);
389
1.87k
            GDALGetMetadataItem(hBand, "foo", nullptr);
390
391
1.87k
            int nFlags = GDALGetMaskFlags(hBand);
392
1.87k
            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand);
393
1.87k
            GDALGetRasterBandXSize(hMaskBand);
394
1.87k
            if (bDoCheckSum && nFlags == GMF_PER_DATASET)
395
11
            {
396
11
                int nBXSize = 0, nBYSize = 0;
397
11
                GDALGetBlockSize(hMaskBand, &nBXSize, &nBYSize);
398
11
                if (nBXSize == 0 || nBYSize == 0 ||
399
11
                    nBXSize > INT_MAX / 2 / nBYSize)
400
0
                {
401
                    // do nothing
402
0
                }
403
11
                else
404
11
                {
405
11
                    GDALChecksumImage(hMaskBand, 0, 0, nXSizeToRead,
406
11
                                      nYSizeToRead);
407
11
                }
408
11
            }
409
410
1.87k
            int nOverviewCount = GDALGetOverviewCount(hBand);
411
3.28k
            for (int i = 0; i < nOverviewCount; i++)
412
1.40k
            {
413
1.40k
                GDALGetOverview(hBand, i);
414
1.40k
            }
415
1.87k
        }
416
417
1.91k
        GDALClose(hDS);
418
1.91k
    }
419
420
2.33k
    auto poDS = std::unique_ptr<GDALDataset>(
421
2.33k
        GDALDataset::Open(pszGDALFilename, GDAL_OF_MULTIDIM_RASTER));
422
2.33k
    if (poDS)
423
404
    {
424
404
        auto poDriver = poDS->GetDriver();
425
404
        const char *pszDriverName = nullptr;
426
404
        if (poDriver)
427
404
            pszDriverName = poDriver->GetDescription();
428
404
        auto poRootGroup = poDS->GetRootGroup();
429
404
        poDS.reset();
430
404
        if (poRootGroup)
431
404
            ExploreGroup(poRootGroup, pszDriverName);
432
404
    }
433
434
2.33k
    CPLPopErrorHandler();
435
2.33k
#ifdef USE_FILESYSTEM
436
2.33k
    VSIUnlink(szTempFilename);
437
#else
438
    VSIUnlink(MEM_FILENAME);
439
#endif
440
2.33k
    return 0;
441
2.33k
}