diff --git a/kitty/graphics.c b/kitty/graphics.c index a96cf1053..2813824fb 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -35,15 +35,52 @@ grman_free(GraphicsManager* self) { return NULL; } -/* static size_t internal_id_counter = 1; */ +static size_t internal_id_counter = 1; + +static inline void* +ensure_space(void *array, size_t *capacity, size_t count, size_t item_size, bool initialize) { + if (count < *capacity) return array; + void *ans = realloc(array, (*capacity) * item_size * 2); + if (ans == NULL) fatal("Out of memory re-allocating array."); + if (initialize) { + memset(((uint8_t*)array) + ((*capacity) * item_size), 0, ((*capacity) * item_size)); + } + *capacity *= 2; + return ans; +} + +static inline Image* +find_or_create_image(GraphicsManager *self, uint32_t id, bool *existing) { + if (id) { + for (size_t i = 0; i < self->image_count; i++) { + if (self->images[i].client_id == id) { + *existing = true; + return self->images + i; + } + } + } + *existing = false; + self->images = ensure_space(self->images, &self->images_capacity, self->image_count, sizeof(Image), true); + return self->images + self->image_count++; +} static void -handle_add_command(GraphicsManager UNUSED *self, const GraphicsCommand UNUSED *g, const uint8_t UNUSED *payload) { +handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t UNUSED *payload) { + bool existing; + Image *img = find_or_create_image(self, g->id, &existing); + if (existing) { + free(img->load_buf); img->load_buf = NULL; + } else { + img->internal_id = internal_id_counter++; + img->client_id = g->id; + } + img->width = g->data_width; img->height = g->data_height; } void grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) { switch(g->action) { + case 0: case 't': handle_add_command(self, g, payload); break; diff --git a/kitty/graphics.h b/kitty/graphics.h index 16f952ae9..208a9ee4a 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -19,6 +19,7 @@ typedef struct { typedef struct { uint32_t gl_id, client_id, width, height; size_t internal_id, refcnt; + uint8_t *load_buf; } Image; diff --git a/kitty/parser.c b/kitty/parser.c index bf4e690b3..fad1dbd78 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -664,6 +664,10 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { default: break; } + if (g.data_width > 10000 || g.data_height > 10000) { + REPORT_ERROR("Image too large"); + return; + } #define A(x) #x, g.x #define U(x) #x, (unsigned int)(g.x) #define I(x) #x, (int)(g.x) diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index 06381c395..2086fa479 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -225,8 +225,10 @@ class TestParser(BaseTest): e(',s=1', 'Malformed graphics control block, invalid key character: 0x2c') e('W=1', 'Malformed graphics control block, invalid key character: 0x57') e('1=1', 'Malformed graphics control block, invalid key character: 0x31') - e('a=1,,w=2', 'Malformed graphics control block, invalid key character: 0x2c') + e('a=t,,w=2', 'Malformed graphics control block, invalid key character: 0x2c') e('s', 'Malformed graphics control block, no = after key') e('s=', 'Malformed graphics control block, expecting an integer value') e('s==', 'Malformed graphics control block, expecting an integer value') e('s=1=', 'Malformed graphics control block, expecting a comma or semi-colon after a value, found: 0x3d') + e('s=20000', 'Image too large') + e('v=20000', 'Image too large')