fix potential segfault
authorPhil Sutter <phil@nwl.cc>
Thu, 25 Dec 2008 14:06:38 +0000 (15:06 +0100)
committerPhil Sutter <phil@nwl.cc>
Sun, 22 Feb 2009 01:55:22 +0000 (02:55 +0100)
The segfault can be triggered by using any diskio object with a
non-existent device, as prepare_diskio_stat() then returns 0 and the
call to obj->data.diskio->current in conky.c:4050 pulls the trigger.

In fact, it's not a problem when the device doesn't exist, as
update_diskio() simply won't fill in any values. So skip the check and
upon device node appearance everything goes it's normal way.

While there, also eliminate double readout of the last line of
/proc/diskstats: after the last line has been read, FEOF is not yet set.
BUT fgets() will return NULL when trying to read the next line. So
better check for fgets()'s return value instead of using feof().

Also strncmp() is useless here, since we really want to compare the full
paths. Besides, text_buffer_size also should be big enough to not make a
difference here.

src/diskio.c

index af9c35a..b805ec7 100644 (file)
@@ -66,10 +66,6 @@ struct diskio_stat *prepare_diskio_stat(const char *s)
 {
        struct diskio_stat *new = 0;
        unsigned i;
-       FILE *fp;
-       int found = 0;
-       char device[text_buffer_size], fbuf[text_buffer_size];
-       static int rep = 0;
 
        if (!s)
                return &diskio_stats[0];
@@ -95,32 +91,6 @@ struct diskio_stat *prepare_diskio_stat(const char *s)
                new->dev = 0;
        }
        new->dev = strndup(s, text_buffer_size);
-
-       /*
-        * check that device actually exists
-        */
-
-       if (!(fp = open_file("/proc/diskstats", &rep))) {
-               ERR("cannot read from /proc/diskstats");
-               return 0;
-       }
-
-       while (!feof(fp)) {
-               fgets(fbuf, text_buffer_size, fp);
-               if (sscanf(fbuf, "%*u %*u %255s %*u %*u %*u %*u %*u %*u %*u", device)) {
-                       // check for device match
-                       if (strncmp(new->dev, device, 256) == 0) {
-                               found = 1;
-                               break;
-                       }
-               }
-       }
-       fclose(fp);
-       fp = 0;
-       if (!found) {
-               ERR("diskio device '%s' does not exist", s);
-               return 0;
-       }
        new->current = 0;
        new->current_read = 0;
        new ->current_write = 0;
@@ -156,8 +126,7 @@ void update_diskio(void)
 
        /* read reads and writes from all disks (minor = 0), including cd-roms
         * and floppies, and sum them up */
-       while (!feof(fp)) {
-               fgets(buf, 512, fp);
+       while (fgets(buf, 512, fp)) {
                col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major,
                        &minor, devbuf, &reads, &writes);
                /* ignore subdevices (they have only 3 matching entries in their line)
@@ -177,8 +146,7 @@ void update_diskio(void)
                        }
                }
                for (i = 1; i < MAX_DISKIO_STATS; i++) {
-                       if (diskio_stats[i].dev &&
-                                       strncmp(devbuf, diskio_stats[i].dev, text_buffer_size) == 0) {
+                       if (diskio_stats[i].dev && !strcmp(devbuf, diskio_stats[i].dev)) {
                                diskio_stats[i].current =
                                        (reads + writes - diskio_stats[i].last) / 2;
                                diskio_stats[i].current_read =