Require data size to be sent for PNG format
This commit is contained in:
@@ -241,9 +241,10 @@ inflate_png(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufsz
|
|||||||
inflate_png_inner(&d, buf, bufsz);
|
inflate_png_inner(&d, buf, bufsz);
|
||||||
if (d.ok) {
|
if (d.ok) {
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
img->load_data.buf_capacity = d.sz;
|
|
||||||
img->load_data.buf = d.decompressed;
|
img->load_data.buf = d.decompressed;
|
||||||
|
img->load_data.buf_capacity = d.sz;
|
||||||
img->load_data.buf_used = d.sz;
|
img->load_data.buf_used = d.sz;
|
||||||
|
img->load_data.data_sz = d.sz;
|
||||||
img->width = d.width; img->height = d.height;
|
img->width = d.width; img->height = d.height;
|
||||||
}
|
}
|
||||||
else free(d.decompressed);
|
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 (tt == 'd' && self->loading_image) init_img = false;
|
||||||
if (init_img) {
|
if (init_img) {
|
||||||
self->loading_image = 0;
|
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");
|
if (g->data_width > 10000 || g->data_height > 10000) ABRT(EINVAL, "Image too large");
|
||||||
remove_images(self, add_trim_predicate);
|
remove_images(self, add_trim_predicate);
|
||||||
img = find_or_create_image(self, g->id, &existing);
|
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;
|
img->width = g->data_width; img->height = g->data_height;
|
||||||
switch(fmt) {
|
switch(fmt) {
|
||||||
case PNG:
|
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.is_4byte_aligned = true;
|
||||||
|
img->load_data.data_sz = g->data_sz;
|
||||||
break;
|
break;
|
||||||
case RGB:
|
case RGB:
|
||||||
case RGBA:
|
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);
|
img->load_data.is_4byte_aligned = fmt == RGBA || (img->width % 4 == 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ABRT(EINVAL, "Unknown image format: %u", fmt);
|
ABRT(EINVAL, "Unknown image format: %u", fmt);
|
||||||
}
|
}
|
||||||
img->load_data.data_sz = sz;
|
|
||||||
if (tt == 'd') {
|
if (tt == 'd') {
|
||||||
if (g->more) self->loading_image = img->internal_id;
|
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);
|
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");
|
if (img->load_data.buf == NULL) fatal("Out of memory while allocating image load data buffer");
|
||||||
img->load_data.buf_used = 0;
|
img->load_data.buf_used = 0;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char action, transmission_type, compressed;
|
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;
|
uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines;
|
||||||
int32_t z_index;
|
int32_t z_index;
|
||||||
size_t payload_sz;
|
size_t payload_sz;
|
||||||
|
|||||||
@@ -551,6 +551,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
y_offset = 'y',
|
y_offset = 'y',
|
||||||
data_height = 'v',
|
data_height = 'v',
|
||||||
data_width = 's',
|
data_width = 's',
|
||||||
|
data_sz = 'S',
|
||||||
num_cells = 'c',
|
num_cells = 'c',
|
||||||
num_lines = 'r',
|
num_lines = 'r',
|
||||||
z_index = 'z'
|
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 KS(n, vs) case n: state = EQUAL; value_state = vs; break
|
||||||
#define U(x) KS(x, UINT)
|
#define U(x) KS(x, UINT)
|
||||||
KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
|
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 U
|
||||||
#undef KS
|
#undef KS
|
||||||
default:
|
default:
|
||||||
@@ -627,7 +628,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
READ_UINT;
|
READ_UINT;
|
||||||
#define U(x) case x: g.x = code; break
|
#define U(x) case x: g.x = code; break
|
||||||
switch(key) {
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
state = AFTER_VALUE;
|
state = AFTER_VALUE;
|
||||||
@@ -671,9 +672,9 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
#define A(x) #x, g.x
|
#define A(x) #x, g.x
|
||||||
#define U(x) #x, (unsigned int)(g.x)
|
#define U(x) #x, (unsigned int)(g.x)
|
||||||
#define I(x) #x, (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),
|
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(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),
|
U(payload_sz), I(z_index),
|
||||||
payload, g.payload_sz
|
payload, g.payload_sz
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ class TestParser(BaseTest):
|
|||||||
k[p] = v.encode('ascii')
|
k[p] = v.encode('ascii')
|
||||||
for f in 'action transmission_type compressed'.split():
|
for f in 'action transmission_type compressed'.split():
|
||||||
k.setdefault(f, b'\0')
|
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)
|
k.setdefault(f, 0)
|
||||||
p = k.pop('payload', '').encode('utf-8')
|
p = k.pop('payload', '').encode('utf-8')
|
||||||
k['payload_sz'] = len(p)
|
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('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, 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')
|
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')
|
e('s=1=', 'Malformed graphics control block, expecting a comma or semi-colon after a value, found: 0x3d')
|
||||||
|
|||||||
Reference in New Issue
Block a user