diff options
author | Peter Wu <peter@lekensteyn.nl> | 2018-08-08 20:00:48 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-08-09 04:52:53 +0000 |
commit | 0be9d149d0feaac8697b993926ffa87e156d7fa4 (patch) | |
tree | fb5b8710e4373ed3085d2324e0b76abb0e7f2f6b /epan/prefs.c | |
parent | 5e2e9de9302f43de899d6d450ed75a17a6d73035 (diff) |
prefs: fix range preferences-related crash after switching profiles
The HTTP dissector could crash (use-after-free) after switching
profiles. In reinit_http, it would assign the return value from
prefs_get_range_value to a global variable which is consulted during
dissection. This value is invalidated while switching profiles (via the
"prefs_reset" function), but is not reinitialized (because the
reinit_http function was not called).
A similar issue exists in the Kafka, UAUDP, VNC, TFTP, Gopher and TDS
dissectors. To reproduce using a capture from the SampleCaptures wiki,
start "wireshark -r vnc-sample.pcap -ovnc.tcp.port:1" and switch
profiles. For the HTTP crash, load any HTTP pcap and switch profiles.
Change-Id: I8725615504a8a82ae46255625a41e2188c07320a
Fixes: v2.3.0rc0-2097-g21a3b8cc71 ("Internalize struct preference")
Reviewed-on: https://code.wireshark.org/review/29030
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/prefs.c')
-rw-r--r-- | epan/prefs.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/epan/prefs.c b/epan/prefs.c index bce63b44d3..adfc91685b 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -4216,26 +4216,36 @@ reset_pref(pref_t *pref) } static void -reset_pref_cb(gpointer data, gpointer user_data _U_) +reset_pref_cb(gpointer data, gpointer user_data) { pref_t *pref = (pref_t *) data; + module_t *module = (module_t *)user_data; + + if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) { + /* + * Some dissectors expect the range (returned via prefs_get_range_value) + * to remain valid if it has not changed. If it did change, then we + * should set "prefs_changed_flags" to ensure that the preference apply + * callback is invoked. That callback will notify dissectors that it + * should no longer assume the range to be valid. + */ + if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) { + /* Optimization: do not invoke apply callback if nothing changed. */ + return; + } + module->prefs_changed_flags |= prefs_get_effect_flags(pref); + } reset_pref(pref); } -typedef struct { - module_t *module; -} reset_pref_arg_t; - /* * Reset all preferences for a module. */ static gboolean reset_module_prefs(const void *key _U_, void *value, void *data _U_) { - reset_pref_arg_t arg; - - arg.module = (module_t *)value; - g_list_foreach(arg.module->prefs, reset_pref_cb, &arg); + module_t *module = (module_t *)value; + g_list_foreach(module->prefs, reset_pref_cb, module); return FALSE; } |