Prevent stack overflows when recursing to coalesce frames

This commit is contained in:
Kovid Goyal 2021-02-05 09:12:08 +05:30
parent 3fc29e0d11
commit 95dc87cf04
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -961,15 +961,16 @@ get_coalesced_frame_data_standalone(const Image *img, const Frame *f, uint8_t *f
static CoalescedFrameData static CoalescedFrameData
get_coalesced_frame_data(GraphicsManager *self, Image *img, const Frame *f) { get_coalesced_frame_data_impl(GraphicsManager *self, Image *img, const Frame *f, unsigned count) {
CoalescedFrameData ans = {0}; CoalescedFrameData ans = {0};
if (count > 32) return ans; // prevent stack overflows, infinite recursion
size_t frame_data_sz; void *frame_data; size_t frame_data_sz; void *frame_data;
ImageAndFrame key = {.image_id = img->internal_id, .frame_id = f->id}; ImageAndFrame key = {.image_id = img->internal_id, .frame_id = f->id};
if (!read_from_cache(self, key, &frame_data, &frame_data_sz)) return ans; if (!read_from_cache(self, key, &frame_data, &frame_data_sz)) return ans;
if (!f->base_frame_id) return get_coalesced_frame_data_standalone(img, f, frame_data); if (!f->base_frame_id) return get_coalesced_frame_data_standalone(img, f, frame_data);
Frame *base = frame_for_id(img, f->base_frame_id); Frame *base = frame_for_id(img, f->base_frame_id);
if (!base) { free(frame_data); return ans; } if (!base) { free(frame_data); return ans; }
CoalescedFrameData base_data = get_coalesced_frame_data(self, img, base); CoalescedFrameData base_data = get_coalesced_frame_data_impl(self, img, base, count + 1);
if (!base_data.buf) { free(frame_data); return ans; } if (!base_data.buf) { free(frame_data); return ans; }
ComposeData d = { ComposeData d = {
.over_px_sz = f->is_opaque ? 3 : 4, .over_px_sz = f->is_opaque ? 3 : 4,
@ -983,6 +984,11 @@ get_coalesced_frame_data(GraphicsManager *self, Image *img, const Frame *f) {
return base_data; return base_data;
} }
static inline CoalescedFrameData
get_coalesced_frame_data(GraphicsManager *self, Image *img, const Frame *f) {
return get_coalesced_frame_data_impl(self, img, f, 0);
}
static void static void
update_current_frame(GraphicsManager *self, Image *img, const CoalescedFrameData *data) { update_current_frame(GraphicsManager *self, Image *img, const CoalescedFrameData *data) {
bool needs_load = data == NULL; bool needs_load = data == NULL;