Require data size to be sent for PNG format

This commit is contained in:
Kovid Goyal 2017-09-28 13:50:28 +05:30
parent d0d769f26b
commit 8e5c4b6f7a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 15 additions and 14 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -204,7 +204,7 @@ def c(**k):
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 @@ def e(cmd, err):
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')