Import opensource codes for security issue. 58/125458/2 accepted/tizen/3.0/common/20170511.174315 accepted/tizen/3.0/ivi/20170510.222436 accepted/tizen/3.0/mobile/20170510.222428 accepted/tizen/3.0/tv/20170510.222431 accepted/tizen/3.0/wearable/20170510.222433 accepted/tizen/unified/20170419.165637 submit/tizen/20170419.100911 submit/tizen_3.0/20170427.113133 submit/tizen_3.0_common/20170511.082856 submit/tizen_3.0_tv/20170427.113227
authorJengHyun Kang <jhyuni.kang@samsung.com>
Mon, 17 Apr 2017 09:54:11 +0000 (18:54 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Mon, 17 Apr 2017 09:54:47 +0000 (18:54 +0900)
 - evdev: user safe_atod to convert the matrix values

Change-Id: I140c95ca030822bf6345b09d16d445af0aebd9e5

src/libinput-private.h
src/udev-seat.c [changed mode: 0755->0644]

index e86df634962338506574ba625e214e94f7d2fb4b..8b6613dafd8dcea98609304e542a3bd9c6756404 100644 (file)
 #include "libinput.h"
 #include "libinput-util.h"
 
+#include <assert.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #ifdef ENABLE_TTRACE
 #include <ttrace.h>
 
old mode 100755 (executable)
new mode 100644 (file)
index f5d0de4..12115e2
 static const char default_seat[] = "seat0";
 static const char default_seat_name[] = "default";
 
+char **
+strv_from_string(const char *in, const char *separators);
+bool
+parse_calibration_property(const char *prop, float calibration_out[6]);
+
 static struct udev_seat *
 udev_seat_create(struct udev_input *input,
                 const char *device_seat,
@@ -61,6 +66,171 @@ libinput_path_has_device(struct libinput *libinput, const char *devnode)
        return false;
 }
 
+static inline bool
+safe_atod(const char *str, double *val)
+{
+       char *endptr;
+       double v;
+       locale_t c_locale;
+
+       /* Create a "C" locale to force strtod to use '.' as separator */
+       c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
+       if (c_locale == (locale_t)0)
+               return false;
+
+       errno = 0;
+       v = strtod_l(str, &endptr, c_locale);
+       freelocale(c_locale);
+       if (errno > 0)
+               return false;
+       if (str == endptr)
+               return false;
+       if (*str != '\0' && *endptr != '\0')
+               return false;
+       if (isnan(v) || isinf(v))
+               return false;
+
+       *val = v;
+       return true;
+}
+
+static inline void
+strv_free(char **strv) {
+       char **s = strv;
+
+       if (!strv)
+               return;
+
+       while (*s != NULL) {
+               free(*s);
+               *s = (char*)0x1; /* detect use-after-free */
+               s++;
+       }
+
+       free (strv);
+}
+
+/**
+ * Return the next word in a string pointed to by state before the first
+ * separator character. Call repeatedly to tokenize a whole string.
+ *
+ * @param state Current state
+ * @param len String length of the word returned
+ * @param separators List of separator characters
+ *
+ * @return The first word in *state, NOT null-terminated
+ */
+static const char *
+next_word(const char **state, size_t *len, const char *separators)
+{
+       const char *next = *state;
+       size_t l;
+
+       if (!*next)
+               return NULL;
+
+       next += strspn(next, separators);
+       if (!*next) {
+               *state = next;
+               return NULL;
+       }
+
+       l = strcspn(next, separators);
+       *state = next + l;
+       *len = l;
+
+       return next;
+}
+
+/**
+ * Return a null-terminated string array with the tokens in the input
+ * string, e.g. "one two\tthree" with a separator list of " \t" will return
+ * an array [ "one", "two", "three", NULL ].
+ *
+ * Use strv_free() to free the array.
+ *
+ * @param in Input string
+ * @param separators List of separator characters
+ *
+ * @return A null-terminated string array or NULL on errors
+ */
+char **
+strv_from_string(const char *in, const char *separators)
+{
+       const char *s, *word;
+       char **strv = NULL;
+       int nelems = 0, idx;
+       size_t l;
+
+       assert(in != NULL);
+
+       s = in;
+       while ((word = next_word(&s, &l, separators)) != NULL)
+              nelems++;
+
+       if (nelems == 0)
+               return NULL;
+
+       nelems++; /* NULL-terminated */
+       strv = zalloc(nelems * sizeof *strv);
+       if (!strv)
+               return NULL;
+
+       idx = 0;
+
+       s = in;
+       while ((word = next_word(&s, &l, separators)) != NULL) {
+               char *copy = strndup(word, l);
+               if (!copy) {
+                       strv_free(strv);
+                       return NULL;
+               }
+
+               strv[idx++] = copy;
+       }
+
+       return strv;
+}
+
+/**
+ * Parses a set of 6 space-separated floats.
+ *
+ * @param prop The string value of the property
+ * @param calibration Returns the six components
+ * @return true on success, false otherwise
+ */
+bool
+parse_calibration_property(const char *prop, float calibration_out[6])
+{
+       int idx;
+       char **strv;
+       float calibration[6];
+
+       if (!prop)
+               return false;
+
+       strv = strv_from_string(prop, " ");
+       if (!strv)
+               return false;
+
+       for (idx = 0; idx < 6; idx++) {
+               double v;
+               if (strv[idx] == NULL || !safe_atod(strv[idx], &v)) {
+                       strv_free(strv);
+                       return false;
+               }
+
+               calibration[idx] = v;
+       }
+
+       strv_free(strv);
+
+       memcpy(calibration_out, calibration, sizeof(calibration));
+
+       return true;
+}
+
+
 static int
 device_added(struct udev_device *udev_device,
             struct udev_input *input,
@@ -118,24 +288,18 @@ device_added(struct udev_device *udev_device,
                udev_device_get_property_value(udev_device,
                                               "LIBINPUT_CALIBRATION_MATRIX");
 
-       if (device->abs.absinfo_x && device->abs.absinfo_y &&
-           calibration_values && sscanf(calibration_values,
-                                        "%f %f %f %f %f %f",
-                                        &calibration[0],
-                                        &calibration[1],
-                                        &calibration[2],
-                                        &calibration[3],
-                                        &calibration[4],
-                                        &calibration[5]) == 6) {
-               evdev_device_set_default_calibration(device, calibration);
-               log_info(&input->base,
-                        "Applying calibration: %f %f %f %f %f %f\n",
-                        calibration[0],
-                        calibration[1],
-                        calibration[2],
-                        calibration[3],
-                        calibration[4],
-                        calibration[5]);
+       if (device->abs.absinfo_x && device->abs.absinfo_y && calibration_values) {
+               if (parse_calibration_property(calibration_values, calibration) == true) {
+                       evdev_device_set_default_calibration(device, calibration);
+                       log_info(&input->base,
+                                "Applying calibration: %f %f %f %f %f %f\n",
+                                calibration[0],
+                                calibration[1],
+                                calibration[2],
+                                calibration[3],
+                                calibration[4],
+                                calibration[5]);
+               }
        }
 
        output_name = udev_device_get_property_value(udev_device, "WL_OUTPUT");