From 8e5c4b6f7a0bfeb3ce369fd68bbbea167525321a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 28 Sep 2017 13:50:28 +0530 Subject: [PATCH] Require data size to be sent for PNG format --- kitty/graphics.c | 14 +++++++------- kitty/graphics.h | 2 +- kitty/parser.c | 9 +++++---- kitty_tests/parser.py | 4 ++-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/kitty/graphics.c b/kitty/graphics.c index 523daa459..81422cc7f 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -241,9 +241,10 @@ inflate_png(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufsz inflate_png_inner(&d, buf, bufsz); if (d.ok) { free_load_data(&img->load_data); - img->load_data.buf_capacity = d.sz; img->load_data.buf = d.decompressed; + img->load_data.buf_capacity = d.sz; img->load_data.buf_used = d.sz; + img->load_data.data_sz = d.sz; img->width = d.width; img->height = d.height; } else free(d.decompressed); @@ -269,8 +270,6 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ if (tt == 'd' && self->loading_image) init_img = false; if (init_img) { self->loading_image = 0; - size_t sz = g->data_width * g->data_height; - if (!sz) ABRT(EINVAL, "Zero width/height not allowed"); if (g->data_width > 10000 || g->data_height > 10000) ABRT(EINVAL, "Image too large"); remove_images(self, add_trim_predicate); img = find_or_create_image(self, g->id, &existing); @@ -284,21 +283,22 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ img->width = g->data_width; img->height = g->data_height; switch(fmt) { case PNG: - sz *= 4; + if (!g->data_sz) ABRT(EINVAL, "Must provide a data size with the PNG format"); img->load_data.is_4byte_aligned = true; + img->load_data.data_sz = g->data_sz; break; case RGB: case RGBA: - sz *= fmt / 8; + img->load_data.data_sz = g->data_width * g->data_height * (fmt / 8); + if (!img->load_data.data_sz) ABRT(EINVAL, "Zero width/height not allowed"); img->load_data.is_4byte_aligned = fmt == RGBA || (img->width % 4 == 0); break; default: ABRT(EINVAL, "Unknown image format: %u", fmt); } - img->load_data.data_sz = sz; if (tt == 'd') { if (g->more) self->loading_image = img->internal_id; - img->load_data.buf_capacity = sz + ((g->compressed || fmt == PNG) ? 4096 : 10); // compression header + img->load_data.buf_capacity = img->load_data.data_sz + (g->compressed ? 1024 : 10); // compression header img->load_data.buf = malloc(img->load_data.buf_capacity + 4); if (img->load_data.buf == NULL) fatal("Out of memory while allocating image load data buffer"); img->load_data.buf_used = 0; diff --git a/kitty/graphics.h b/kitty/graphics.h index b0cb3c7d9..4f2da19d4 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -9,7 +9,7 @@ typedef struct { unsigned char action, transmission_type, compressed; - uint32_t format, more, id; + uint32_t format, more, id, data_sz; uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines; int32_t z_index; size_t payload_sz; diff --git a/kitty/parser.c b/kitty/parser.c index 03f8e7e45..478bf6cb2 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -551,6 +551,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { y_offset = 'y', data_height = 'v', data_width = 's', + data_sz = 'S', num_cells = 'c', num_lines = 'r', z_index = 'z' @@ -574,7 +575,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { #define KS(n, vs) case n: state = EQUAL; value_state = vs; break #define U(x) KS(x, UINT) KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT); - U(format); U(more); U(id); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); + U(format); U(more); U(id); U(data_sz); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); #undef U #undef KS default: @@ -627,7 +628,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { READ_UINT; #define U(x) case x: g.x = code; break switch(key) { - U(format); U(more); U(id); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); + U(format); U(more); U(id); U(data_sz); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); default: break; } state = AFTER_VALUE; @@ -671,9 +672,9 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { #define A(x) #x, g.x #define U(x) #x, (unsigned int)(g.x) #define I(x) #x, (int)(g.x) - REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command", + REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command", A(action), A(transmission_type), A(compressed), - U(format), U(more), U(id), + U(format), U(more), U(id), U(data_sz), U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines), U(payload_sz), I(z_index), payload, g.payload_sz diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index 2f93e0733..780222761 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -204,7 +204,7 @@ class TestParser(BaseTest): k[p] = v.encode('ascii') for f in 'action transmission_type compressed'.split(): k.setdefault(f, b'\0') - for f in 'format more id width height x_offset y_offset data_height data_width num_cells num_lines z_index'.split(): + for f in 'format more id data_sz width height x_offset y_offset data_height data_width num_cells num_lines z_index'.split(): k.setdefault(f, 0) p = k.pop('payload', '').encode('utf-8') k['payload_sz'] = len(p) @@ -231,5 +231,5 @@ class TestParser(BaseTest): 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==', 'Malformed graphics control block, expecting an integer value for key: s') e('s=1=', 'Malformed graphics control block, expecting a comma or semi-colon after a value, found: 0x3d')