I was looking through the viewer source and noticed that the ZRLE decoder
(viewer-core/ZrleDecoder.cpp) doesn't validate palette indices before using
them to look up colours.
In readPaletteRleTile(), the subencoding type byte controls how many palette
entries exist (type - 128, range 2-127). The colour index byte is also
server-controlled; after stripping the high bit it can be 0-127 - but
there's no check it's less than the palette size before the memcpy on
line 315. Sending a 2-entry palette with index 127 reads 500 bytes past
the allocation end and copies them into the framebuffer.
Same flaw in readPackedPaletteTile() line 264: type=5 gives paletteSize=5
but the 0x0F bitmask allows color 0-15.
Steps to reproduce (custom server):
Expected: decoder throws/skips out-of-range indices.
Actual: reads past end of palette allocation.
Attached PoCs demonstrate both the heap infoleak and the crash.
Version: 2.8.87.