From 91723d7328b128d20626731f98b414c773a98ba1 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sat, 7 Jan 2017 16:35:54 +0000 Subject: 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 --- gdk-pixbuf/io-ico.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file 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; } } -- cgit v1.2.1