aboutsummaryrefslogtreecommitdiffstats
path: root/epan/register.c
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2022-01-11 02:11:10 -0800
committerGuy Harris <gharris@sonic.net>2022-01-11 19:56:14 +0000
commit18748abb5e3c536d3e60e76967e2ee4ce43117f9 (patch)
tree091a5d7df37d47c46d6cc98707b992e8c4e5da05 /epan/register.c
parent16e0ba7dd7bad5ffc11211ee61c895e10b249acb (diff)
Fix handling of dissector registration errors.
Report all registration errors with REPORT_DISSECTOR_BUG(). In the workers for register_all_protocols() and register_all_protocol_handlers(), use TRY/CATCH/ENDTRY to catch DissectorError exceptions thrown by REPORT_DISSECTOR_BUG() when registering dissectors. Return the error message from the main thread routine and, when joining the worker thread, if there's an error message returned, throw it in the current thread, so that it gets caught by the main libwireshark initialization code. Fixes the crash in #17856.
Diffstat (limited to 'epan/register.c')
-rw-r--r--epan/register.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/epan/register.c b/epan/register.c
index e8387c112a..cd6bf735c7 100644
--- a/epan/register.c
+++ b/epan/register.c
@@ -12,6 +12,9 @@
#include "ws_attributes.h"
#include <glib.h>
+
+#include <epan/exceptions.h>
+
#include "epan/dissectors/dissectors.h"
static const char *cur_cb_name = NULL;
@@ -31,13 +34,30 @@ static void set_cb_name(const char *proto) {
static void *
register_all_protocols_worker(void *arg _U_)
{
- for (gulong i = 0; i < dissector_reg_proto_count; i++) {
- set_cb_name(dissector_reg_proto[i].cb_name);
- dissector_reg_proto[i].cb_func();
+ void *volatile error_message = NULL;
+
+ TRY {
+ for (gulong i = 0; i < dissector_reg_proto_count; i++) {
+ set_cb_name(dissector_reg_proto[i].cb_name);
+ dissector_reg_proto[i].cb_func();
+ }
}
+ CATCH(DissectorError) {
+ /*
+ * This is probably a dissector, or something it calls,
+ * calling REPORT_DISSECTOR_ERROR() in a registration
+ * routine or something else outside the normal dissection
+ * code path.
+ *
+ * The message gets freed by ENDTRY, so we must make a copy
+ * of it.
+ */
+ error_message = g_strdup(GET_MESSAGE);
+ }
+ ENDTRY;
g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE));
- return NULL;
+ return (void *) error_message;
}
void
@@ -47,6 +67,7 @@ register_all_protocols(register_cb cb, gpointer cb_data)
register_cb_done_q = g_async_queue_new();
gboolean called_back = FALSE;
GThread *rapw_thread;
+ const char *error_message;
rapw_thread = g_thread_new("register_all_protocols_worker", &register_all_protocols_worker, NULL);
while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) {
@@ -58,7 +79,9 @@ register_all_protocols(register_cb cb, gpointer cb_data)
called_back = TRUE;
}
}
- g_thread_join(rapw_thread);
+ error_message = (const char *) g_thread_join(rapw_thread);
+ if (error_message != NULL)
+ THROW_MESSAGE(DissectorError, error_message);
if (cb && !called_back) {
cb(RA_REGISTER, "finished", cb_data);
}
@@ -67,13 +90,30 @@ register_all_protocols(register_cb cb, gpointer cb_data)
static void *
register_all_protocol_handoffs_worker(void *arg _U_)
{
- for (gulong i = 0; i < dissector_reg_handoff_count; i++) {
- set_cb_name(dissector_reg_handoff[i].cb_name);
- dissector_reg_handoff[i].cb_func();
+ void *volatile error_message = NULL;
+
+ TRY {
+ for (gulong i = 0; i < dissector_reg_handoff_count; i++) {
+ set_cb_name(dissector_reg_handoff[i].cb_name);
+ dissector_reg_handoff[i].cb_func();
+ }
+ }
+ CATCH(DissectorError) {
+ /*
+ * This is probably a dissector, or something it calls,
+ * calling REPORT_DISSECTOR_ERROR() in a registration
+ * routine or something else outside the normal dissection
+ * code path.
+ *
+ * The message gets freed by ENDTRY, so we must make a copy
+ * of it.
+ */
+ error_message = g_strdup(GET_MESSAGE);
}
+ ENDTRY;
g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE));
- return NULL;
+ return (void *) error_message;
}
void
@@ -83,6 +123,7 @@ register_all_protocol_handoffs(register_cb cb, gpointer cb_data)
const char *cb_name;
gboolean called_back = FALSE;
GThread *raphw_thread;
+ const char *error_message;
raphw_thread = g_thread_new("register_all_protocol_handoffs_worker", &register_all_protocol_handoffs_worker, NULL);
while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) {
@@ -94,7 +135,9 @@ register_all_protocol_handoffs(register_cb cb, gpointer cb_data)
called_back = TRUE;
}
}
- g_thread_join(raphw_thread);
+ error_message = (const char *) g_thread_join(raphw_thread);
+ if (error_message != NULL)
+ THROW_MESSAGE(DissectorError, error_message);
if (cb && !called_back) {
cb(RA_HANDOFF, "finished", cb_data);
}