Whamcloud - gitweb
libext2fs: fix short-read bugs in unix_io's bounce buffer handling
authorMatthias Andree <matthias.andree@gmx.de>
Tue, 13 Sep 2016 20:34:33 +0000 (16:34 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 13 Sep 2016 20:35:15 +0000 (16:35 -0400)
Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/unix_io.c

index ec92bf5..27b6a95 100644 (file)
@@ -163,6 +163,7 @@ static errcode_t raw_read_blk(io_channel channel,
        ext2_loff_t     location;
        int             actual = 0;
        unsigned char   *buf = bufv;
+       ssize_t         really_read = 0;
 
        size = (count < 0) ? -count : count * channel->block_size;
        data->io_stats.bytes_read += size;
@@ -227,12 +228,17 @@ static errcode_t raw_read_blk(io_channel channel,
 bounce_read:
        while (size > 0) {
                actual = read(data->dev, data->bounce, channel->block_size);
-               if (actual != channel->block_size)
+               if (actual != channel->block_size) {
+                       actual = really_read;
+                       buf -= really_read;
+                       size += really_read;
                        goto short_read;
+               }
                actual = size;
                if (size > channel->block_size)
                        actual = channel->block_size;
                memcpy(buf, data->bounce, actual);
+               really_read += actual;
                size -= actual;
                buf += actual;
        }
@@ -329,8 +335,12 @@ bounce_write:
                        actual = read(data->dev, data->bounce,
                                      channel->block_size);
                        if (actual != channel->block_size) {
-                               retval = EXT2_ET_SHORT_READ;
-                               goto error_out;
+                               if (actual < 0) {
+                                       retval = EXT2_ET_SHORT_READ;
+                                       goto error_out;
+                               }
+                               memset(data->bounce + actual, 0,
+                                      channel->block_size - actual);
                        }
                }
                actual = size;