From a92e38603902b22c5b20fecefa5da3d2a233516c Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Tue, 13 Nov 2018 04:18:21 +0100 Subject: jbig2dec: Only print repeated error/warning messages once. --- base/sjbig2.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++--- base/sjbig2.h | 4 +++ jbig2dec/jbig2dec.c | 58 ++++++++++++++++++++++++++++++++++-- 3 files changed, 142 insertions(+), 6 deletions(-) diff --git a/base/sjbig2.c b/base/sjbig2.c index cf308869f..89b26b414 100644 --- a/base/sjbig2.c +++ b/base/sjbig2.c @@ -66,10 +66,61 @@ s_jbig2decode_error(void *callback_data, const char *msg, Jbig2Severity severity if (error_data) { - if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) { - dmlprintf3(error_data->memory, "jbig2dec %s %s %s\n", type, msg, segment); - } else { - if_debug3m('w', error_data->memory, "[w] jbig2dec %s %s %s\n", type, msg, segment); + char *message; + int len; + + len = snprintf(NULL, 0, "jbig2dec %s %s %s", type, msg, segment); + if (len < 0) + return; + + message = (char *)gs_alloc_bytes(error_data->memory, len + 1, "sjbig2decode_error(message)"); + if (message == NULL) + return; + + len = snprintf(message, len + 1, "jbig2dec %s %s %s", type, msg, segment); + if (len < 0) + { + gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)"); + return; + } + + if (error_data->last_message != NULL && strcmp(message, error_data->last_message)) { + if (error_data->repeats > 1) + { + if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) { + dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats); + } else { + if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats); + } + } + gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)"); + error_data->last_message = message; + error_data->severity = severity; + error_data->type = type; + error_data->repeats = 0; + } + else if (error_data->last_message != NULL) { + error_data->repeats++; + if (error_data->repeats % 1000000 == 0) + { + if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) { + dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times so far\n", error_data->repeats); + } else { + if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times so far\n", error_data->repeats); + } + } + gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)"); + } + else if (error_data->last_message == NULL) { + if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) { + dmlprintf1(error_data->memory, "%s\n", message); + } else { + if_debug1m('w', error_data->memory, "[w] %s\n", message); + } + error_data->last_message = message; + error_data->severity = severity; + error_data->type = type; + error_data->repeats = 0; } } else @@ -86,6 +137,29 @@ s_jbig2decode_error(void *callback_data, const char *msg, Jbig2Severity severity } } +static void +s_jbig2decode_flush_errors(void *callback_data) +{ + s_jbig2_callback_data_t *error_data = (s_jbig2_callback_data_t *)callback_data; + + if (error_data == NULL) + return; + + if (error_data->last_message != NULL) { + if (error_data->repeats > 1) + { + if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) { + dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats); + } else { + if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats); + } + } + gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)"); + error_data->last_message = NULL; + error_data->repeats = 0; + } +} + /* invert the bits in a buffer */ /* jbig2 and postscript have different senses of what pixel value is black, so we must invert the image */ @@ -171,6 +245,8 @@ s_jbig2decode_init(stream_state * ss) if (state->callback_data) { state->callback_data->memory = ss->memory->non_gc_memory; state->callback_data->error = 0; + state->callback_data->last_message = NULL; + state->callback_data->repeats = 0; /* initialize the decoder with the parsed global context if any */ state->decode_ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, global_ctx, s_jbig2decode_error, state->callback_data); @@ -249,11 +325,13 @@ s_jbig2decode_release(stream_state *ss) if (state->decode_ctx) { if (state->image) jbig2_release_page(state->decode_ctx, state->image); state->image = NULL; + s_jbig2decode_flush_errors(state->callback_data); jbig2_ctx_free(state->decode_ctx); state->decode_ctx = NULL; } if (state->callback_data) { gs_memory_t *mem = state->callback_data->memory; + gs_free_object(state->callback_data->memory, state->callback_data->last_message, "s_jbig2decode_release(message)"); gs_free_object(mem, state->callback_data, "s_jbig2decode_release(callback_data)"); state->callback_data = NULL; } diff --git a/base/sjbig2.h b/base/sjbig2.h index f94f4b0ec..50289ce94 100644 --- a/base/sjbig2.h +++ b/base/sjbig2.h @@ -28,6 +28,10 @@ typedef struct s_jbig2_callback_data_s { gs_memory_t *memory; int error; + char *last_message; + Jbig2Severity severity; + const char *type; + long repeats; } s_jbig2_callback_data_t; /* See zfjbig2.c for details. */ diff --git a/jbig2dec/jbig2dec.c b/jbig2dec/jbig2dec.c index cc6358d49..1a455c01f 100644 --- a/jbig2dec/jbig2dec.c +++ b/jbig2dec/jbig2dec.c @@ -66,6 +66,10 @@ typedef struct { SHA1_CTX *hash_ctx; char *output_filename; jbig2dec_format output_format; + char *last_message; + Jbig2Severity severity; + char *type; + long repeats; } jbig2dec_params_t; static int print_version(void); @@ -248,9 +252,11 @@ print_usage(void) static void error_callback(void *error_callback_data, const char *buf, Jbig2Severity severity, int32_t seg_idx) { - const jbig2dec_params_t *params = (jbig2dec_params_t *) error_callback_data; + jbig2dec_params_t *params = (jbig2dec_params_t *) error_callback_data; char *type; char segment[22]; + int len; + char *message; switch (severity) { case JBIG2_SEVERITY_DEBUG: @@ -280,7 +286,52 @@ error_callback(void *error_callback_data, const char *buf, Jbig2Severity severit else snprintf(segment, sizeof(segment), "(segment 0x%02x)", seg_idx); - fprintf(stderr, "jbig2dec %s %s %s\n", type, buf, segment); + len = snprintf(NULL, 0, "jbig2dec %s %s %s", type, buf, segment); + if (len < 0) { + return; + } + + message = malloc(len + 1); + if (message == NULL) { + return; + } + + len = snprintf(message, len + 1, "jbig2dec %s %s %s", type, buf, segment); + if (len < 0) + { + free(message); + return; + } + + if (params->last_message != NULL && strcmp(message, params->last_message)) { + if (params->repeats > 1) + fprintf(stderr, "jbig2dec %s last message repeated %ld times\n", params->type, params->repeats); + fprintf(stderr, "%s\n", message); + free(params->last_message); + params->last_message = message; + params->severity = severity; + params->type = type; + params->repeats = 0; + } else if (params->last_message != NULL) { + params->repeats++; + if (params->repeats % 1000000 == 0) + fprintf(stderr, "jbig2dec %s last message repeated %ld times so far\n", params->type, params->repeats); + free(message); + } else if (params->last_message == NULL) { + fprintf(stderr, "%s\n", message); + params->last_message = message; + params->severity = severity; + params->type = type; + params->repeats = 0; + } +} + +static void +flush_errors(jbig2dec_params_t *params) +{ + if (params->repeats > 1) { + fprintf(stderr, "jbig2dec last message repeated %ld times\n", params->repeats); + } } static char * @@ -387,6 +438,8 @@ main(int argc, char **argv) params.output_filename = NULL; params.output_format = jbig2dec_format_none; params.embedded = 0; + params.last_message = NULL; + params.repeats = 0; filearg = parse_options(argc, argv, ¶ms); @@ -541,6 +594,7 @@ main(int argc, char **argv) result = 0; cleanup: + flush_errors(¶ms); jbig2_ctx_free(ctx); if (params.output_filename) free(params.output_filename); -- cgit v1.2.1