From: Bruno Haible Date: Wed, 13 Aug 2025 20:19:19 +0000 (+0200) Subject: its: Improve libxml error handling. X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fgettext.git its: Improve libxml error handling. When there is a non-fatal error, the previous code would just print a message to stderr and continue the operation, without affecting the exit code. * gettext-tools/src/its.c: Include , . (xml_error_exit): New variable. (structured_error): Longjmp to xml_error_exit. (generic_error): New function. (its_rule_list_add_from_file, its_rule_list_add_from_string, its_rule_list_extract, its_merge_context_merge, its_merge_context_alloc, its_merge_context_write): Invoke also xmlSetGenericErrorFunc. Use setjmp to abort the operation when a non-fatal error occurs. --- diff --git a/gettext-tools/src/its.c b/gettext-tools/src/its.c index bfa9c99cb..57572a818 100644 --- a/gettext-tools/src/its.c +++ b/gettext-tools/src/its.c @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include @@ -81,6 +83,9 @@ /* ----------------------------- Error handling ----------------------------- */ +/* The non-local exit to invoke when a non-fatal libxml error occurs. */ +static jmp_buf xml_error_exit; + static void /* Adapt to API change in libxml 2.12.0. See . */ @@ -92,6 +97,22 @@ structured_error (void *data, xmlError *err) { error (err->level == XML_ERR_FATAL ? EXIT_FAILURE : 0, 0, _("%s error: %s"), "libxml2", err->message); + longjmp (xml_error_exit, 1); +} + +/* Generic errors are marked "deprecated" in the documentation, but functions + like xmlDocFormatDump actually do produce them. */ +static void generic_error (void *data, const char *message, ...) + LIBXML_ATTR_FORMAT (2, 3); +static void +generic_error (void *data, const char *message, ...) +{ + va_list args; + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + longjmp (xml_error_exit, 1); } /* --------------------------------- Values --------------------------------- */ @@ -1603,11 +1624,20 @@ its_rule_list_add_from_file (struct its_rule_list_ty *rules, return false; } - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); + + result = its_rule_list_add_from_doc (rules, doc); + } + else + /* Caught a libxml error. */ + result = false; - result = its_rule_list_add_from_doc (rules, doc); xmlFreeDoc (doc); + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); return result; } @@ -1634,11 +1664,20 @@ its_rule_list_add_from_string (struct its_rule_list_ty *rules, return false; } - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); + + result = its_rule_list_add_from_doc (rules, doc); + } + else + /* Caught a libxml error. */ + result = false; - result = its_rule_list_add_from_doc (rules, doc); xmlFreeDoc (doc); + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); return result; } @@ -2031,8 +2070,6 @@ its_rule_list_extract (its_rule_list_ty *rules, its_extract_callback_ty callback) { xmlDoc *doc; - struct its_node_list_ty nodes; - size_t i; doc = xmlReadFd (fileno (fp), logical_filename, NULL, XML_PARSE_NONET @@ -2047,24 +2084,35 @@ its_rule_list_extract (its_rule_list_ty *rules, return; } - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); + + its_rule_list_apply (rules, doc); - its_rule_list_apply (rules, doc); + struct its_node_list_ty nodes; + memset (&nodes, 0, sizeof (struct its_node_list_ty)); + its_rule_list_extract_nodes (rules, + &nodes, + xmlDocGetRootElement (doc)); - memset (&nodes, 0, sizeof (struct its_node_list_ty)); - its_rule_list_extract_nodes (rules, - &nodes, - xmlDocGetRootElement (doc)); + size_t i; + for (i = 0; i < nodes.nitems; i++) + its_rule_list_extract_text (rules, nodes.items[i], + logical_filename, + mdlp->item[0]->messages, + callback); - for (i = 0; i < nodes.nitems; i++) - its_rule_list_extract_text (rules, nodes.items[i], - logical_filename, - mdlp->item[0]->messages, - callback); + free (nodes.items); + } + else + /* Caught a libxml error. */ + ; - free (nodes.items); xmlFreeDoc (doc); + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); } @@ -3024,16 +3072,23 @@ its_merge_context_merge (its_merge_context_ty *context, message_list_ty *mlp, bool replace_text) { - size_t i; - - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); - for (i = 0; i < context->nodes.nitems; i++) - its_merge_context_merge_node (context, context->nodes.items[i], - language, - mlp, - replace_text); + size_t i; + for (i = 0; i < context->nodes.nitems; i++) + its_merge_context_merge_node (context, context->nodes.items[i], + language, + mlp, + replace_text); + } + else + /* Caught a libxml error. */ + ; + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); } @@ -3057,20 +3112,33 @@ its_merge_context_alloc (its_rule_list_ty *rules, return NULL; } - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); - its_rule_list_apply (rules, doc); + its_rule_list_apply (rules, doc); - result = XMALLOC (struct its_merge_context_ty); - result->rules = rules; - result->doc = doc; + result = XMALLOC (struct its_merge_context_ty); + result->rules = rules; + result->doc = doc; - /* Collect translatable nodes. */ - memset (&result->nodes, 0, sizeof (struct its_node_list_ty)); - its_rule_list_extract_nodes (result->rules, - &result->nodes, - xmlDocGetRootElement (result->doc)); + /* Collect translatable nodes. */ + memset (&result->nodes, 0, sizeof (struct its_node_list_ty)); + its_rule_list_extract_nodes (result->rules, + &result->nodes, + xmlDocGetRootElement (result->doc)); + } + else + { + /* Caught a libxml error. */ + if (result != NULL) + free (result); + result = NULL; + xmlFreeDoc (doc); + } + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); return result; } @@ -3079,10 +3147,18 @@ void its_merge_context_write (struct its_merge_context_ty *context, FILE *fp) { - xmlSetStructuredErrorFunc (NULL, structured_error); + if (setjmp (xml_error_exit) == 0) + { + xmlSetStructuredErrorFunc (NULL, structured_error); + xmlSetGenericErrorFunc (NULL, generic_error); - xmlDocFormatDump (fp, context->doc, 1); + xmlDocFormatDump (fp, context->doc, 1); + } + else + /* Caught a libxml error. */ + ; + xmlSetGenericErrorFunc (NULL, NULL); xmlSetStructuredErrorFunc (NULL, NULL); }