[gdk-pixbuf] io-ico: Fix option parsing to be locale-independent



commit 91723d7328b128d20626731f98b414c773a98ba1
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sat Jan 7 16:35:54 2017 +0000

    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 files changed, 54 insertions(+), 4 deletions(-)
---
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c
index 2b0441f..ddb804c 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;
                        }
 
                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]