static int decode_wdlt(uint8_t *frame, int width, int height, const uint8_t *src, const uint8_t *src_end) { const uint8_t *frame_end = frame + width * height; uint8_t *line_ptr; int count, i, v, lines, segments; lines = bytestream_get_le16(&src); if (lines > height || src >= src_end) return -1; while (lines--) { segments = bytestream_get_le16(&src); while ((segments & 0xC000) == 0xC000) { unsigned delta = -((int16_t)segments * width); if (frame_end - frame <= delta) return -1; frame += delta; segments = bytestream_get_le16(&src); } if (segments & 0x8000) { frame[width - 1] = segments & 0xFF; segments = bytestream_get_le16(&src); } line_ptr = frame; frame += width; while (segments--) { if (src_end - src < 2) return -1; if (frame - line_ptr <= *src) return -1; line_ptr += *src++; count = (int8_t)*src++; if (count >= 0) { if (frame - line_ptr < count*2 || src_end - src < count*2) return -1; bytestream_get_buffer(&src, line_ptr, count*2); line_ptr += count * 2; } else { count = -count; if (frame - line_ptr < count*2 || src_end - src < 2) return -1; v = bytestream_get_le16(&src); for (i = 0; i < count; i++) bytestream_put_le16(&line_ptr, v); } } } return 0; }