Fix crash gif decoding

Before this fix, it were read memory positions beyond the end of the local colormap in the function GifMakeMapObject.
This commit is contained in:
Gaspar Capello 2020-07-07 16:17:07 -03:00 committed by David Capello
parent 8a3f32b47f
commit b7f1555eb3

View File

@ -458,8 +458,14 @@ private:
} }
else if (!m_hasLocalColormaps) { else if (!m_hasLocalColormaps) {
if (!global) { if (!global) {
if (!m_firstLocalColormap) if (!m_firstLocalColormap) {
m_firstLocalColormap = GifMakeMapObject(256, colormap->Colors); m_firstLocalColormap = GifMakeMapObject(256, nullptr);
for (int i=0; i<colormap->ColorCount; ++i) {
m_firstLocalColormap->Colors[i].Red = colormap->Colors[i].Red;
m_firstLocalColormap->Colors[i].Green = colormap->Colors[i].Green;
m_firstLocalColormap->Colors[i].Blue = colormap->Colors[i].Blue;
}
}
global = m_firstLocalColormap; global = m_firstLocalColormap;
} }
@ -503,13 +509,13 @@ private:
// With this we avoid discarding the transparent index when a // With this we avoid discarding the transparent index when a
// frame indicates that it uses a specific index as transparent // frame indicates that it uses a specific index as transparent
// but the image is completely opaque anyway. // but the image is completely opaque anyway.
if (m_localTransparentIndex >= 0 && if (!m_opaque && m_frameNum == 0 && m_localTransparentIndex >= 0 &&
m_localTransparentIndex < ncolors) { m_localTransparentIndex < ncolors) {
usedEntries[m_localTransparentIndex] = true; usedEntries[m_localTransparentIndex] = true;
} }
for (const auto& i : LockImageBits<IndexedTraits>(frameImage)) { for (const auto& i : LockImageBits<IndexedTraits>(frameImage)) {
if (i >= 0 && i < ncolors) if (i >= 0 && i < ncolors && i != m_localTransparentIndex)
usedEntries[i] = true; usedEntries[i] = true;
} }
} }
@ -524,8 +530,14 @@ private:
// Check if we need an extra color equal to the bg color in a // Check if we need an extra color equal to the bg color in a
// transparent frameImage. // transparent frameImage.
bool needsExtraBgColor = false; bool needsExtraBgColor = false;
bool needCheckLocalTransparent = m_bgIndex != m_localTransparentIndex ||
(ncolors > m_localTransparentIndex
&& m_localTransparentIndex >= 0
&& usedEntries[m_localTransparentIndex]);
if (m_sprite->pixelFormat() == IMAGE_INDEXED && if (m_sprite->pixelFormat() == IMAGE_INDEXED &&
!m_opaque && m_bgIndex != m_localTransparentIndex) { !m_opaque &&
needCheckLocalTransparent) {
for (const auto& i : LockImageBits<IndexedTraits>(frameImage)) { for (const auto& i : LockImageBits<IndexedTraits>(frameImage)) {
if (i == m_bgIndex) { if (i == m_bgIndex) {
needsExtraBgColor = true; needsExtraBgColor = true;
@ -623,8 +635,10 @@ private:
// the sprite pixel format will be converted in RGBA image, and the colors will // the sprite pixel format will be converted in RGBA image, and the colors will
// be picked from the sprite palette, instead of m_firstLocalColorMap. // be picked from the sprite palette, instead of m_firstLocalColorMap.
if (m_firstLocalColormap && m_firstLocalColormap->ColorCount > j) { if (m_firstLocalColormap && m_firstLocalColormap->ColorCount > j) {
// We need add this last color to m_firstLocalColormap, because // We need add this extra color to m_firstLocalColormap, because
// it was not considered in the function getFrameColormap. // it might has not been considered in the first getFrameColormap execution.
// (this happen when: in the first execution of getFrameColormap function
// an extra color was not needed)
m_firstLocalColormap->Colors[j].Red = rgba_getr(palette->getEntry(j)); m_firstLocalColormap->Colors[j].Red = rgba_getr(palette->getEntry(j));
m_firstLocalColormap->Colors[j].Green = rgba_getg(palette->getEntry(j)); m_firstLocalColormap->Colors[j].Green = rgba_getg(palette->getEntry(j));
m_firstLocalColormap->Colors[j].Blue = rgba_getb(palette->getEntry(j)); m_firstLocalColormap->Colors[j].Blue = rgba_getb(palette->getEntry(j));