mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-26 10:12:17 +02:00
Graphics: Disallow PNGs of size greater than MAX_IMAGE_DIMENSION to match behavior with loading RGB data
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include "png-reader.h"
|
#include "png-reader.h"
|
||||||
PyTypeObject GraphicsManager_Type;
|
PyTypeObject GraphicsManager_Type;
|
||||||
|
|
||||||
|
#define MAX_IMAGE_DIMENSION 10000u
|
||||||
#define DEFAULT_STORAGE_LIMIT 320u * (1024u * 1024u)
|
#define DEFAULT_STORAGE_LIMIT 320u * (1024u * 1024u)
|
||||||
#define REPORT_ERROR(...) { log_error(__VA_ARGS__); }
|
#define REPORT_ERROR(...) { log_error(__VA_ARGS__); }
|
||||||
#define RAII_CoalescedFrameData(name, initializer) __attribute__((cleanup(cfd_free))) CoalescedFrameData name = initializer
|
#define RAII_CoalescedFrameData(name, initializer) __attribute__((cleanup(cfd_free))) CoalescedFrameData name = initializer
|
||||||
@@ -380,7 +381,7 @@ png_error_handler(png_read_data *d UNUSED, const char *code, const char *msg) {
|
|||||||
static bool
|
static bool
|
||||||
inflate_png(LoadData *load_data, uint8_t *buf, size_t bufsz) {
|
inflate_png(LoadData *load_data, uint8_t *buf, size_t bufsz) {
|
||||||
png_read_data d = {.err_handler=png_error_handler};
|
png_read_data d = {.err_handler=png_error_handler};
|
||||||
inflate_png_inner(&d, buf, bufsz);
|
inflate_png_inner(&d, buf, bufsz, MAX_IMAGE_DIMENSION);
|
||||||
if (d.ok) {
|
if (d.ok) {
|
||||||
free_load_data(load_data);
|
free_load_data(load_data);
|
||||||
load_data->buf = d.decompressed;
|
load_data->buf = d.decompressed;
|
||||||
@@ -415,7 +416,7 @@ print_png_read_error(png_read_data *d, const char *code, const char* msg) {
|
|||||||
bool
|
bool
|
||||||
png_from_data(void *png_data, size_t png_data_sz, const char *path_for_error_messages, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz) {
|
png_from_data(void *png_data, size_t png_data_sz, const char *path_for_error_messages, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz) {
|
||||||
png_read_data d = {.err_handler=print_png_read_error};
|
png_read_data d = {.err_handler=print_png_read_error};
|
||||||
inflate_png_inner(&d, png_data, png_data_sz);
|
inflate_png_inner(&d, png_data, png_data_sz, MAX_IMAGE_DIMENSION);
|
||||||
if (!d.ok) {
|
if (!d.ok) {
|
||||||
log_error("Failed to decode PNG image at: %s with error: %s", path_for_error_messages, d.error.used > 0 ? d.error.buf : "");
|
log_error("Failed to decode PNG image at: %s with error: %s", path_for_error_messages, d.error.used > 0 ? d.error.buf : "");
|
||||||
free(d.decompressed); free(d.row_pointers); free(d.error.buf);
|
free(d.decompressed); free(d.row_pointers); free(d.error.buf);
|
||||||
@@ -693,7 +694,6 @@ initialize_load_data(GraphicsManager *self, const GraphicsCommand *g, Image *img
|
|||||||
tt = g->transmission_type ? g->transmission_type : 'd'; \
|
tt = g->transmission_type ? g->transmission_type : 'd'; \
|
||||||
fmt = g->format ? g->format : RGBA; \
|
fmt = g->format ? g->format : RGBA; \
|
||||||
}
|
}
|
||||||
#define MAX_IMAGE_DIMENSION 10000u
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
upload_to_gpu(GraphicsManager *self, Image *img, const bool is_opaque, const bool is_4byte_aligned, const uint8_t *data) {
|
upload_to_gpu(GraphicsManager *self, Image *img, const bool is_opaque, const bool is_4byte_aligned, const uint8_t *data) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ read_png_warn_handler(png_structp UNUSED png_ptr, png_const_charp msg) {
|
|||||||
#define ABRT(code, msg) { if(d->err_handler) d->err_handler(d, #code, msg); goto err; }
|
#define ABRT(code, msg) { if(d->err_handler) d->err_handler(d, #code, msg); goto err; }
|
||||||
|
|
||||||
void
|
void
|
||||||
inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz) {
|
inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz, int max_image_dimension) {
|
||||||
struct fake_file f = {.buf = buf, .sz = bufsz};
|
struct fake_file f = {.buf = buf, .sz = bufsz};
|
||||||
png_structp png = NULL;
|
png_structp png = NULL;
|
||||||
png_infop info = NULL;
|
png_infop info = NULL;
|
||||||
@@ -64,6 +64,10 @@ inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz) {
|
|||||||
png_byte color_type, bit_depth;
|
png_byte color_type, bit_depth;
|
||||||
d->width = png_get_image_width(png, info);
|
d->width = png_get_image_width(png, info);
|
||||||
d->height = png_get_image_height(png, info);
|
d->height = png_get_image_height(png, info);
|
||||||
|
// libpng uses too much memory for overly large images
|
||||||
|
if (d->width > max_image_dimension || d->height > max_image_dimension) {
|
||||||
|
ABRT(ENOMEM, "PNG image is too large");
|
||||||
|
}
|
||||||
color_type = png_get_color_type(png, info);
|
color_type = png_get_color_type(png, info);
|
||||||
bit_depth = png_get_bit_depth(png, info);
|
bit_depth = png_get_bit_depth(png, info);
|
||||||
double image_gamma;
|
double image_gamma;
|
||||||
@@ -208,7 +212,7 @@ load_png_data(PyObject *self UNUSED, PyObject *args) {
|
|||||||
const char *data;
|
const char *data;
|
||||||
if (!PyArg_ParseTuple(args, "s#", &data, &sz)) return NULL;
|
if (!PyArg_ParseTuple(args, "s#", &data, &sz)) return NULL;
|
||||||
png_read_data d = {.err_handler=png_error_handler};
|
png_read_data d = {.err_handler=png_error_handler};
|
||||||
inflate_png_inner(&d, (const uint8_t*)data, sz);
|
inflate_png_inner(&d, (const uint8_t*)data, sz, 10000);
|
||||||
PyObject *ans = NULL;
|
PyObject *ans = NULL;
|
||||||
if (d.ok && !PyErr_Occurred()) {
|
if (d.ok && !PyErr_Occurred()) {
|
||||||
ans = Py_BuildValue("y#ii", d.decompressed, (int)d.sz, d.width, d.height);
|
ans = Py_BuildValue("y#ii", d.decompressed, (int)d.sz, d.width, d.height);
|
||||||
|
|||||||
@@ -27,5 +27,5 @@ typedef struct png_read_data {
|
|||||||
} error;
|
} error;
|
||||||
} png_read_data;
|
} png_read_data;
|
||||||
|
|
||||||
void inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz);
|
void inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz, int max_image_dimension);
|
||||||
const char* png_from_32bit_rgba(uint32_t *data, size_t width, size_t height, size_t *out_size, bool flip_vertically);
|
const char* png_from_32bit_rgba(uint32_t *data, size_t width, size_t height, size_t *out_size, bool flip_vertically);
|
||||||
|
|||||||
Reference in New Issue
Block a user