From 9deaedbfc595317976bc93c5486f87e3b45c6d53 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 3 Sep 2015 16:17:11 +1000 Subject: [PATCH] Add some device sanity checking Don't allow devices with zero profiles, zero resolutions, etc. Signed-off-by: Peter Hutterer --- src/libratbag.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/libratbag.c b/src/libratbag.c index 28398b73..3b2729ff 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -297,6 +297,83 @@ ratbag_device_destroy(struct ratbag_device *device) free(device); } +static inline bool +ratbag_sanity_check_device(struct ratbag_device *device) +{ + struct ratbag *ratbag = device->ratbag; + struct ratbag_profile *profile = NULL; + struct ratbag_resolution *res = NULL; + bool has_active = false; + bool has_default = false; + unsigned int nres, nprofiles; + bool rc = false; + unsigned int i; + + /* arbitrary number: max 16 profiles, does any mouse have more? but + * since we have num_profiles unsigned, it also checks for + * accidental negative */ + if (device->num_profiles == 0 || device->num_profiles > 16) { + log_bug_libratbag(ratbag, + "%s: invalid number of profiles %d\n", + device->name, + device->num_profiles); + goto out; + } + + nprofiles = ratbag_device_get_num_profiles(device); + for (i = 0; i < nprofiles; i++) { + profile = ratbag_device_get_profile_by_index(device, i); + /* Allow max 1 default profile */ + if (profile->is_default) { + if (has_default) { + log_bug_libratbag(ratbag, + "%s: multiple default profiles\n", + device->name); + goto out; + } + has_default = true; + } + + /* Allow max 1 active profile */ + if (profile->is_active) { + if (has_active) { + log_bug_libratbag(ratbag, + "%s: multiple active profiles\n", + device->name); + goto out; + } + has_active = true; + } + + nres = ratbag_profile_get_num_resolutions(profile); + if (nres == 0 || nres > 16) { + log_bug_libratbag(ratbag, + "%s: minimum 1 resolution required\n", + device->name); + goto out; + } + + ratbag_profile_unref(profile); + profile = NULL; + } + + /* Require 1 active profile */ + if (!has_active) { + log_bug_libratbag(ratbag, + "%s: no active profile found\n", + device->name); + goto out; + } + + rc = true; + +out: + ratbag_profile_unref(profile); + ratbag_resolution_unref(res); + + return rc; +} + static inline bool ratbag_match_id(const struct input_id *dev_id, const struct input_id *match_id) { @@ -326,9 +403,14 @@ ratbag_find_driver(struct ratbag_device *device, const struct input_id *dev_id) device->driver = driver; rc = driver->probe(device, matched_id); if (rc == 0) { - log_debug(ratbag, "driver match found\n"); - device->svg_name = matching_id->svg_filename; - return driver; + if (!ratbag_sanity_check_device(device)) { + driver->remove(device); + return NULL; + } else { + log_debug(ratbag, "driver match found\n"); + device->svg_name = matching_id->svg_filename; + return driver; + } } device->driver = NULL;