Skip to content

Commit bfa9d8a

Browse files
authored
Merge pull request #12169 from rouault/fix_ossfuzz_411459952
HFA and PDF: avoid integer division by zero in CreateCopy() when one of dataset dimension is zero
2 parents b80609f + 5e0e45d commit bfa9d8a

File tree

5 files changed

+95
-93
lines changed

5 files changed

+95
-93
lines changed

autotest/gcore/hfa_write.py

Lines changed: 64 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828
# test that we can write a small file with a custom layer name.
2929

3030

31-
def test_hfa_write_desc():
31+
def test_hfa_write_desc(tmp_path):
32+
33+
img_path = tmp_path / "test_desc.img"
3234

3335
src_ds = gdal.Open("data/byte.tif")
3436

35-
new_ds = gdal.GetDriverByName("HFA").CreateCopy("tmp/test_desc.img", src_ds)
37+
new_ds = gdal.GetDriverByName("HFA").CreateCopy(img_path, src_ds)
3638

3739
bnd = new_ds.GetRasterBand(1)
3840
bnd.SetDescription("CustomBandName")
@@ -41,88 +43,69 @@ def test_hfa_write_desc():
4143
src_ds = None
4244
new_ds = None
4345

44-
new_ds = gdal.Open("tmp/test_desc.img")
46+
new_ds = gdal.Open(img_path)
4547
bnd = new_ds.GetRasterBand(1)
4648
assert bnd.GetDescription() == "CustomBandName", "Didn't get custom band name."
4749

48-
bnd = None
49-
new_ds = None
50-
51-
gdal.GetDriverByName("HFA").Delete("tmp/test_desc.img")
52-
5350

5451
###############################################################################
55-
# test writing 4 bit files.
56-
57-
58-
def test_hfa_write_4bit():
59-
drv = gdal.GetDriverByName("HFA")
60-
src_ds = gdal.Open("data/byte.tif")
61-
ds = drv.CreateCopy("tmp/4bit.img", src_ds, options=["NBITS=1"])
62-
ds = None
63-
src_ds = None
64-
65-
ds = gdal.Open("tmp/4bit.img")
66-
cs = ds.GetRasterBand(1).Checksum()
52+
# test writing n-bit files.
6753

68-
assert cs == 252, "Got wrong checksum on 4bit image."
6954

70-
ds = None
71-
72-
drv.Delete("tmp/4bit.img")
73-
74-
75-
###############################################################################
76-
# test writing 4 bit files compressed.
55+
@pytest.mark.parametrize(
56+
"options,expected_cs",
57+
[
58+
(["NBITS=1"], 252),
59+
(["NBITS=1", "COMPRESSED=YES"], 252),
60+
(["NBITS=2"], 718),
61+
(["NBITS=2", "COMPRESSED=YES"], 718),
62+
(["NBITS=4"], 2578),
63+
(["NBITS=4", "COMPRESSED=YES"], 2578),
64+
],
65+
)
66+
def test_hfa_write_nbits(tmp_path, options, expected_cs):
7767

68+
img_path = tmp_path / "nbits.img"
7869

79-
def test_hfa_write_4bit_compressed():
8070
drv = gdal.GetDriverByName("HFA")
8171
src_ds = gdal.Open("data/byte.tif")
82-
ds = drv.CreateCopy("tmp/4bitc.img", src_ds, options=["NBITS=1", "COMPRESSED=YES"])
72+
ds = drv.CreateCopy(img_path, src_ds, options=options)
8373
ds = None
8474
src_ds = None
8575

86-
ds = gdal.Open("tmp/4bitc.img")
76+
ds = gdal.Open(img_path)
8777
cs = ds.GetRasterBand(1).Checksum()
88-
89-
assert cs == 252, "Got wrong checksum on 4bit image."
90-
91-
ds = None
92-
93-
drv.Delete("tmp/4bitc.img")
78+
assert cs == expected_cs
9479

9580

9681
###############################################################################
9782
# Test creating a file with a nodata value, and fetching otherwise unread
9883
# blocks and verifying they are the nodata value. (#2427)
9984

10085

101-
def test_hfa_write_nd_invalid():
86+
def test_hfa_write_nd_invalid(tmp_path):
87+
88+
img_path = tmp_path / "ndinvalid.img"
10289

10390
drv = gdal.GetDriverByName("HFA")
104-
ds = drv.Create("tmp/ndinvalid.img", 512, 512, 1, gdal.GDT_Byte, [])
91+
ds = drv.Create(img_path, 512, 512, 1, gdal.GDT_Byte, [])
10592
ds.GetRasterBand(1).SetNoDataValue(200)
10693
ds = None
10794

108-
ds = gdal.Open("tmp/ndinvalid.img")
95+
ds = gdal.Open(img_path)
10996
cs = ds.GetRasterBand(1).Checksum()
11097

11198
assert cs == 29754, "Got wrong checksum on invalid image."
11299

113-
ds = None
114-
115-
drv.Delete("tmp/ndinvalid.img")
116-
117100

118101
###############################################################################
119102
# Test updating .rrd overviews in place (#2524).
120103

121104

122105
def test_hfa_update_overviews(tmp_path):
123106

124-
img_path = str(tmp_path / "small.img")
125-
rrd_path = str(tmp_path / "small.rrd")
107+
img_path = tmp_path / "small.img"
108+
rrd_path = tmp_path / "small.rrd"
126109

127110
shutil.copyfile("data/small_ov.img", img_path)
128111
shutil.copyfile("data/small_ov.rrd", rrd_path)
@@ -131,7 +114,6 @@ def test_hfa_update_overviews(tmp_path):
131114
result = ds.BuildOverviews(overviewlist=[2])
132115

133116
assert result == 0, "BuildOverviews() failed."
134-
ds = None
135117

136118

137119
###############################################################################
@@ -140,8 +122,8 @@ def test_hfa_update_overviews(tmp_path):
140122

141123
def test_hfa_clean_external_overviews(tmp_path):
142124

143-
img_path = str(tmp_path / "small.img")
144-
rrd_path = str(tmp_path / "small.rrd")
125+
img_path = tmp_path / "small.img"
126+
rrd_path = tmp_path / "small.rrd"
145127

146128
shutil.copyfile("data/small_ov.img", img_path)
147129
shutil.copyfile("data/small_ov.rrd", rrd_path)
@@ -160,17 +142,18 @@ def test_hfa_clean_external_overviews(tmp_path):
160142

161143
assert not os.path.exists(rrd_path)
162144

163-
gdal.GetDriverByName("HFA").Delete(img_path)
164-
165145

166146
###############################################################################
167147
# Test writing high frequency data (#2525).
168148

169149

170-
def test_hfa_bug_2525():
150+
def test_hfa_bug_2525(tmp_path):
151+
152+
tmp_filename = tmp_path / "test_hfa"
153+
171154
drv = gdal.GetDriverByName("HFA")
172155
ds = drv.Create(
173-
"tmp/test_hfa.img", 64, 64, 1, gdal.GDT_UInt16, options=["COMPRESSED=YES"]
156+
tmp_filename, 64, 64, 1, gdal.GDT_UInt16, options=["COMPRESSED=YES"]
174157
)
175158
import struct
176159

@@ -243,40 +226,33 @@ def test_hfa_bug_2525():
243226
)
244227
for i in range(64):
245228
ds.GetRasterBand(1).WriteRaster(0, i, 64, 1, data)
246-
ds = None
247-
248-
drv.Delete("tmp/test_hfa.img")
229+
ds.Close()
249230

250231

251232
###############################################################################
252233
# Test building external overviews with HFA_USE_RRD=YES
253234

254235

255-
def test_hfa_use_rrd():
236+
def test_hfa_use_rrd(tmp_path):
237+
238+
tmp_filename = tmp_path / "small.img"
256239

257-
shutil.copyfile("data/small_ov.img", "tmp/small.img")
240+
shutil.copyfile("data/small_ov.img", tmp_filename)
258241

259242
with gdal.config_option("HFA_USE_RRD", "YES"):
260-
ds = gdal.Open("tmp/small.img", gdal.GA_Update)
243+
ds = gdal.Open(tmp_filename, gdal.GA_Update)
261244
result = ds.BuildOverviews(overviewlist=[2])
262245

263246
assert result == 0, "BuildOverviews() failed."
264247
ds = None
265248

266-
try:
267-
os.stat("tmp/small.rrd")
268-
except OSError:
269-
pytest.fail("small.rrd not present.")
249+
assert os.path.exists(tmp_path / "small.rrd")
270250

271-
ds = gdal.Open("tmp/small.img")
251+
ds = gdal.Open(tmp_filename)
272252
assert (
273253
ds.GetRasterBand(1).GetOverview(0).Checksum() == 26148
274254
), "Unexpected checksum."
275255

276-
ds = None
277-
278-
gdal.GetDriverByName("HFA").Delete("tmp/small.img")
279-
280256

281257
###############################################################################
282258
# Test fix for #4831
@@ -285,7 +261,7 @@ def test_hfa_use_rrd():
285261
@pytest.mark.require_driver("BMP")
286262
def test_hfa_update_existing_aux_overviews(tmp_path):
287263

288-
tmp_filename = str(tmp_path / "hfa_update_existing_aux_overviews.bmp")
264+
tmp_filename = tmp_path / "hfa_update_existing_aux_overviews.bmp"
289265

290266
with gdal.config_option("USE_RRD", "YES"):
291267

@@ -351,8 +327,6 @@ def test_hfa_update_existing_aux_overviews(tmp_path):
351327
pytest.fail()
352328
ds = None
353329

354-
gdal.GetDriverByName("BMP").Delete(tmp_filename)
355-
356330

357331
###############################################################################
358332
# Get the driver, and verify a few things about it.
@@ -436,25 +410,22 @@ def test_hfa_create_compress(filename, checksum, testfunction):
436410
getattr(ut, testfunction)()
437411

438412

439-
def test_hfa_create_compress_big_block():
440-
src_ds = gdal.GetDriverByName("MEM").Create(
441-
"/vsimem/big_block.img", 128, 128, 1, gdal.GDT_UInt32
442-
)
413+
def test_hfa_create_compress_big_block(tmp_vsimem):
414+
filename = tmp_vsimem / "test.img"
415+
src_ds = gdal.GetDriverByName("MEM").Create("", 128, 128, 1, gdal.GDT_UInt32)
443416
src_ds.GetRasterBand(1).Fill(4 * 1000 * 1000 * 1000)
444417
src_ds.GetRasterBand(1).WriteRaster(0, 0, 1, 1, struct.pack("I", 0))
445418
gdal.GetDriverByName("HFA").CreateCopy(
446-
"/vsimem/big_block.img", src_ds, options=["COMPRESS=YES", "BLOCKSIZE=128"]
419+
filename, src_ds, options=["COMPRESS=YES", "BLOCKSIZE=128"]
447420
)
448-
ds = gdal.Open("/vsimem/big_block.img")
421+
ds = gdal.Open(filename)
449422
got_data = ds.GetRasterBand(1).ReadRaster()
450-
ds = None
451-
gdal.Unlink("/vsimem/big_block.img")
452423
assert got_data == src_ds.GetRasterBand(1).ReadRaster()
453424

454425

455426
# GCPs go to PAM currently
456-
def test_hfa_create_gcp():
457-
filename = "/vsimem/test.img"
427+
def test_hfa_create_gcp(tmp_vsimem):
428+
filename = tmp_vsimem / "test.img"
458429
ds = gdal.GetDriverByName("HFA").Create(filename, 1, 1)
459430
gcp1 = gdal.GCP()
460431
gcp1.GCPPixel = 0
@@ -465,9 +436,15 @@ def test_hfa_create_gcp():
465436
sr.ImportFromEPSG(4326)
466437
assert ds.SetGCPs((gcp1,), sr.ExportToWkt()) == gdal.CE_None
467438
ds = None
468-
ds = gdal.Open(filename)
469-
assert ds.GetGCPCount() == 1
470-
assert ds.GetGCPSpatialRef() is not None
471-
assert len(ds.GetGCPs()) == 1
472-
ds = None
473-
gdal.GetDriverByName("HFA").Delete(filename)
439+
440+
with gdal.Open(filename) as ds:
441+
assert ds.GetGCPCount() == 1
442+
assert ds.GetGCPSpatialRef() is not None
443+
assert len(ds.GetGCPs()) == 1
444+
445+
446+
@pytest.mark.require_driver("L1B")
447+
def test_hfa_create_copy_from_ysize_0(tmp_vsimem):
448+
src_ds = gdal.Open("../gdrivers/data/l1b/n12gac8bit_truncated_ysize_0_1band.l1b")
449+
with pytest.raises(Exception, match="nXSize == 0 || nYSize == 0 not supported"):
450+
gdal.GetDriverByName("HFA").CreateCopy(tmp_vsimem / "out.img", src_ds)
Binary file not shown.

autotest/gdrivers/pdf.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3140,3 +3140,15 @@ def test_pdf_gdal_driver_pdf_list_layer():
31403140
alg["input"] = "data/byte.tif"
31413141
with pytest.raises(Exception, match="is not a PDF"):
31423142
alg.Run()
3143+
3144+
3145+
###############################################################################
3146+
#
3147+
3148+
3149+
@gdaltest.enable_exceptions()
3150+
@pytest.mark.require_driver("L1B")
3151+
def test_pdf_create_copy_from_ysize_0(tmp_vsimem):
3152+
src_ds = gdal.Open("../gdrivers/data/l1b/n12gac8bit_truncated_ysize_0_1band.l1b")
3153+
with pytest.raises(Exception, match="nWidth == 0 || nHeight == 0 not supported"):
3154+
gdal.GetDriverByName("PDF").CreateCopy(tmp_vsimem / "out.pdf", src_ds)

frmts/hfa/hfaopen.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,12 @@ HFAHandle HFACreate(const char *pszFilename, int nXSize, int nYSize, int nBands,
22272227
EPTType eDataType, char **papszOptions)
22282228

22292229
{
2230+
if (nXSize == 0 || nYSize == 0)
2231+
{
2232+
CPLError(CE_Failure, CPLE_NotSupported,
2233+
"nXSize == 0 || nYSize == 0 not supported");
2234+
return nullptr;
2235+
}
22302236
int nBlockSize = 64;
22312237
const char *pszValue = CSLFetchNameValue(papszOptions, "BLOCKSIZE");
22322238

frmts/pdf/pdfcreatecopy.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4150,16 +4150,20 @@ GDALDataset *GDALPDFCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
41504150
GDALProgressFunc pfnProgress,
41514151
void *pProgressData)
41524152
{
4153-
int nBands = poSrcDS->GetRasterCount();
4154-
int nWidth = poSrcDS->GetRasterXSize();
4155-
int nHeight = poSrcDS->GetRasterYSize();
4156-
4157-
if (!pfnProgress(0.0, nullptr, pProgressData))
4158-
return nullptr;
4153+
const int nBands = poSrcDS->GetRasterCount();
4154+
const int nWidth = poSrcDS->GetRasterXSize();
4155+
const int nHeight = poSrcDS->GetRasterYSize();
41594156

41604157
/* -------------------------------------------------------------------- */
41614158
/* Some some rudimentary checks */
41624159
/* -------------------------------------------------------------------- */
4160+
if (nWidth == 0 || nHeight == 0)
4161+
{
4162+
CPLError(CE_Failure, CPLE_NotSupported,
4163+
"nWidth == 0 || nHeight == 0 not supported");
4164+
return nullptr;
4165+
}
4166+
41634167
if (nBands != 1 && nBands != 3 && nBands != 4)
41644168
{
41654169
CPLError(CE_Failure, CPLE_NotSupported,
@@ -4491,6 +4495,9 @@ GDALDataset *GDALPDFCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
44914495
const char *pszJavascriptFile =
44924496
CSLFetchNameValue(papszOptions, "JAVASCRIPT_FILE");
44934497

4498+
if (!pfnProgress(0.0, nullptr, pProgressData))
4499+
return nullptr;
4500+
44944501
/* -------------------------------------------------------------------- */
44954502
/* Create file. */
44964503
/* -------------------------------------------------------------------- */

0 commit comments

Comments
 (0)