/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 | } 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 | } |
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 | } 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 | } |
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 | } |
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 | } |
|