mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-11 02:59:40 +02:00
Better PNG load error reporting
This commit is contained in:
@@ -305,7 +305,7 @@ err:
|
||||
}
|
||||
|
||||
static void
|
||||
png_error_handler(const char *code, const char *msg) {
|
||||
png_error_handler(png_read_data *d UNUSED, const char *code, const char *msg) {
|
||||
set_command_failed_response(code, "%s", msg);
|
||||
}
|
||||
|
||||
@@ -333,6 +333,17 @@ add_trim_predicate(Image *img) {
|
||||
return !img->root_frame_data_loaded || (!img->client_id && !img->refs);
|
||||
}
|
||||
|
||||
static void
|
||||
print_png_read_error(png_read_data *d, const char *code, const char* msg) {
|
||||
if (d->error.used >= d->error.capacity) {
|
||||
size_t cap = MAX(2 * d->error.capacity, 1024 + d->error.used);
|
||||
d->error.buf = realloc(d->error.buf, cap);
|
||||
if (!d->error.buf) return;
|
||||
d->error.capacity = cap;
|
||||
}
|
||||
d->error.used += snprintf(d->error.buf + d->error.used, d->error.capacity - d->error.used, "%s: %s ", code, msg);
|
||||
}
|
||||
|
||||
bool
|
||||
png_from_file_pointer(FILE *fp, const char *path_for_error_messages, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz) {
|
||||
size_t capacity = 16*1024, pos = 0;
|
||||
@@ -356,16 +367,16 @@ png_from_file_pointer(FILE *fp, const char *path_for_error_messages, uint8_t** d
|
||||
return false;
|
||||
}
|
||||
}
|
||||
png_read_data d = {0};
|
||||
png_read_data d = {.err_handler=print_png_read_error};
|
||||
inflate_png_inner(&d, buf, pos);
|
||||
free(buf);
|
||||
if (!d.ok) {
|
||||
free(d.decompressed); free(d.row_pointers);
|
||||
log_error("Failed to decode PNG image at: %s", path_for_error_messages);
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
*data = d.decompressed;
|
||||
free(d.row_pointers);
|
||||
free(d.row_pointers); free(d.error.buf);
|
||||
*sz = d.sz;
|
||||
*height = d.height; *width = d.width;
|
||||
return true;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "data-types.h"
|
||||
#include "png-reader.h"
|
||||
#include "cleanup.h"
|
||||
#include "state.h"
|
||||
@@ -26,7 +27,7 @@ read_png_from_buffer(png_structp png, png_bytep out, png_size_t length) {
|
||||
|
||||
struct custom_error_handler {
|
||||
jmp_buf jb;
|
||||
png_error_handler_func err_handler;
|
||||
png_read_data *d;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -34,7 +35,7 @@ read_png_error_handler(png_structp png_ptr, png_const_charp msg) {
|
||||
struct custom_error_handler *eh;
|
||||
eh = png_get_error_ptr(png_ptr);
|
||||
if (eh == NULL) fatal("read_png_error_handler: could not retrieve error handler");
|
||||
if(eh->err_handler) eh->err_handler("EBADPNG", msg);
|
||||
if(eh->d->err_handler) eh->d->err_handler(eh->d, "EBADPNG", msg);
|
||||
longjmp(eh->jb, 1);
|
||||
}
|
||||
|
||||
@@ -43,14 +44,14 @@ read_png_warn_handler(png_structp UNUSED png_ptr, png_const_charp msg) {
|
||||
if (global_state.debug_rendering) log_error("libpng WARNING: %s", msg);
|
||||
}
|
||||
|
||||
#define ABRT(code, msg) { if(d->err_handler) d->err_handler(#code, msg); goto err; }
|
||||
#define ABRT(code, msg) { if(d->err_handler) d->err_handler(d, #code, msg); goto err; }
|
||||
|
||||
void
|
||||
inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz) {
|
||||
struct fake_file f = {.buf = buf, .sz = bufsz};
|
||||
png_structp png = NULL;
|
||||
png_infop info = NULL;
|
||||
struct custom_error_handler eh = {.err_handler = d->err_handler};
|
||||
struct custom_error_handler eh = {.d = d};
|
||||
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, &eh, read_png_error_handler, read_png_warn_handler);
|
||||
if (!png) ABRT(ENOMEM, "Failed to create PNG read structure");
|
||||
info = png_create_info_struct(png);
|
||||
@@ -131,8 +132,8 @@ err:
|
||||
}
|
||||
|
||||
static void
|
||||
png_error_handler(const char *code, const char *msg) {
|
||||
PyErr_Format(PyExc_ValueError, "[%s] %s", code, msg);
|
||||
png_error_handler(png_read_data *d UNUSED, const char *code, const char *msg) {
|
||||
if (!PyErr_Occurred()) PyErr_Format(PyExc_ValueError, "[%s] %s", code, msg);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
||||
@@ -6,16 +6,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data-types.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <png.h>
|
||||
typedef void(*png_error_handler_func)(const char*, const char*);
|
||||
typedef struct {
|
||||
|
||||
typedef struct png_read_data png_read_data;
|
||||
|
||||
typedef void(*png_error_handler_func)(png_read_data *d, const char*, const char*);
|
||||
|
||||
typedef struct png_read_data {
|
||||
uint8_t *decompressed;
|
||||
bool ok;
|
||||
png_bytep *row_pointers;
|
||||
int width, height;
|
||||
size_t sz;
|
||||
png_error_handler_func err_handler;
|
||||
struct {
|
||||
char *buf;
|
||||
size_t used, capacity;
|
||||
} error;
|
||||
} png_read_data;
|
||||
|
||||
void inflate_png_inner(png_read_data *d, const uint8_t *buf, size_t bufsz);
|
||||
|
||||
Reference in New Issue
Block a user