summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2017-01-07 16:35:54 +0000
committerPhilip Withnall <withnall@endlessm.com>2017-02-17 11:21:02 +0000
commit91723d7328b128d20626731f98b414c773a98ba1 (patch)
treece8e073e6acd938f80d73726c0f1b1bcf0a381ed
parent0f538573aca0950eac37a407aed5529f41019200 (diff)
downloadgdk-pixbuf-91723d7328b128d20626731f98b414c773a98ba1.tar.gz
io-ico: Fix option parsing to be locale-independent
sscanf() and strtol() are both locale-dependent. In addition, the return value of sscanf() was not being checked (so it could fail without being noticed), and there was no bounds checking being performed. Bounds checking is now performed, although the bounds have been chosen for conservative backwards-compatibility, and may not be the most appropriate. Coverity CID: 1388522 https://bugzilla.gnome.org/show_bug.cgi?id=776990
-rw-r--r--gdk-pixbuf/io-ico.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c
index 2b0441fa2..ddb804c3a 100644
--- a/gdk-pixbuf/io-ico.c
+++ b/gdk-pixbuf/io-ico.c
@@ -1240,6 +1240,47 @@ write_icon (FILE *f, GSList *entries)
}
}
+/* Locale-independent signed integer string parser, base 10.
+ * @minimum and @maximum are valid inclusively. */
+static gboolean
+ascii_strtoll (const gchar *str,
+ gint64 minimum,
+ gint64 maximum,
+ gint64 *out,
+ GError **error)
+{
+ gint64 retval;
+ const gchar *end_ptr;
+
+ errno = 0;
+ retval = g_ascii_strtoll (str, (gchar **) &end_ptr, 10);
+
+ if (errno != 0) {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ g_strerror (errno));
+ return FALSE;
+ } else if (end_ptr == str || *end_ptr != '\0') {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Argument is not an integer: %s", str);
+ return FALSE;
+ } else if ((maximum < G_MAXINT64 && retval > maximum) ||
+ (minimum > G_MININT64 && retval < minimum)) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Argument should be in range [%" G_GINT64_FORMAT
+ ", %" G_GINT64_FORMAT "]: %s",
+ minimum, maximum, str);
+ return FALSE;
+ }
+
+ g_assert (retval >= minimum && retval <= maximum);
+
+ if (out != NULL)
+ *out = retval;
+
+ return TRUE;
+}
+
static gboolean
gdk_pixbuf__ico_image_save (FILE *f,
GdkPixbuf *pixbuf,
@@ -1265,15 +1306,24 @@ gdk_pixbuf__ico_image_save (FILE *f,
gchar **viter;
for (kiter = keys, viter = values; *kiter && *viter; kiter++, viter++) {
- char *endptr;
+ gint64 out;
if (strcmp (*kiter, "depth") == 0) {
- sscanf (*viter, "%d", &icon->depth);
+ if (!ascii_strtoll (*viter, 1, 32,
+ &out, error))
+ return FALSE;
+ icon->depth = out;
}
else if (strcmp (*kiter, "x_hot") == 0) {
- hot_x = strtol (*viter, &endptr, 10);
+ if (!ascii_strtoll (*viter, G_MININT, G_MAXINT,
+ &out, error))
+ return FALSE;
+ hot_x = out;
}
else if (strcmp (*kiter, "y_hot") == 0) {
- hot_y = strtol (*viter, &endptr, 10);
+ if (!ascii_strtoll (*viter, G_MININT, G_MAXINT,
+ &out, error))
+ return FALSE;
+ hot_y = out;
}
}