Skip to content

Commit 1928161

Browse files
authored
Merge pull request #14683 from rouault/fix_14682
gdal raster rgb-to-palette: fix crash with transparency / very low number of colors
2 parents d14d35d + c7b1708 commit 1928161

3 files changed

Lines changed: 39 additions & 3 deletions

File tree

alg/gdalmediancut.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ int GDALComputeMedianCutPCTInternal(
600600
/* ==================================================================== */
601601
/* STEP 4: assign colors to all boxes */
602602
/* ==================================================================== */
603+
if (nColorCounter > 0)
603604
{
604605
Colorbox *ptr = usedboxes;
605606
if (panPixelCountPerColorTableEntry)

apps/gdalalg_raster_rgb_to_palette.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,18 @@ bool GDALRasterRGBToPaletteAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
253253
oCT = std::move(*(poCT.get()));
254254
}
255255
}
256-
257-
m_colorCount = oCT.GetColorEntryCount();
258256
}
259257

258+
m_colorCount = oCT.GetColorEntryCount();
259+
260260
if (m_dstNoData >= 0)
261261
{
262262
for (int i = std::min(255, m_colorCount); i > m_dstNoData; --i)
263263
{
264-
oCT.SetColorEntry(i, oCT.GetColorEntry(i - 1));
264+
// Create a temporary copy to avoid use after free when SetColorEntry()
265+
// resizes the underlying vector.
266+
const GDALColorEntry sEntry = *(oCT.GetColorEntry(i - 1));
267+
oCT.SetColorEntry(i, &sEntry);
265268
}
266269

267270
poTmpDS->GetRasterBand(1)->SetNoDataValue(m_dstNoData);

autotest/utilities/test_gdalalg_raster_rgb_to_palette.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,35 @@ def test_gdalalg_raster_rgb_to_palette_bit_depth_8(tmp_vsimem):
329329
) as alg:
330330
ds = alg.Output()
331331
assert ds.GetRasterBand(1).Checksum() == 7593
332+
333+
334+
def test_gdalalg_raster_rgb_to_palette_rgba_single_color():
335+
336+
src_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 4)
337+
src_ds.GetRasterBand(1).SetColorInterpretation(gdal.GCI_RedBand)
338+
src_ds.GetRasterBand(2).SetColorInterpretation(gdal.GCI_GreenBand)
339+
src_ds.GetRasterBand(3).SetColorInterpretation(gdal.GCI_BlueBand)
340+
src_ds.GetRasterBand(4).SetColorInterpretation(gdal.GCI_AlphaBand)
341+
src_ds.GetRasterBand(4).Fill(255)
342+
343+
with gdal.Run(get_alg(), input=src_ds, output="", output_format="MEM") as alg:
344+
ds = alg.Output()
345+
assert ds.GetRasterBand(1).GetColorTable().GetCount() == 2
346+
assert ds.GetRasterBand(1).GetColorTable().GetColorEntry(0) == (0, 0, 0, 0)
347+
assert ds.GetRasterBand(1).GetColorTable().GetColorEntry(1) == (0, 0, 0, 255)
348+
assert ds.GetRasterBand(1).Checksum() == 1
349+
350+
351+
def test_gdalalg_raster_rgb_to_palette_rgba_all_transparent():
352+
353+
src_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 4)
354+
src_ds.GetRasterBand(1).SetColorInterpretation(gdal.GCI_RedBand)
355+
src_ds.GetRasterBand(2).SetColorInterpretation(gdal.GCI_GreenBand)
356+
src_ds.GetRasterBand(3).SetColorInterpretation(gdal.GCI_BlueBand)
357+
src_ds.GetRasterBand(4).SetColorInterpretation(gdal.GCI_AlphaBand)
358+
359+
with gdal.Run(get_alg(), input=src_ds, output="", output_format="MEM") as alg:
360+
ds = alg.Output()
361+
assert ds.GetRasterBand(1).GetColorTable().GetCount() == 1
362+
assert ds.GetRasterBand(1).GetColorTable().GetColorEntry(0) == (0, 0, 0, 0)
363+
assert ds.GetRasterBand(1).Checksum() == 0

0 commit comments

Comments
 (0)