[PATCH] erofs-utils: lib: fix infinite loop on EOF in erofs_io_xcopy
Ajay Rajera
newajay.11r at gmail.com
Fri Mar 20 11:20:52 AEDT 2026
erofs_io_xcopy() has a fallback do-while loop for when the
kernel fast-paths (copy_file_range/sendfile) do not handle all
the data. The loop does:
ret = erofs_io_read(vin, buf, ret);
if (ret < 0)
return ret;
if (ret > 0) { ... pos += ret; }
len -= ret;
} while (len);
When erofs_io_read() returns 0 (EOF -- source exhausted before
all bytes were copied), only the ret < 0 and ret > 0 branches
were handled. Since ret == 0, `len -= ret` is a no-op and
`while (len)` stays true, causing the loop to spin forever at
100% CPU with no error and no progress.
This can be triggered when building an EROFS image from an input
file that is shorter than expected -- e.g. a truncated source
file, a pipe/FIFO that closes early, or a file being modified
concurrently during mkfs.
Fix it by treating a zero return as an error (-ENODATA) so the
caller fails cleanly instead of hanging indefinitely.
Also fix the long-standing 'pading' -> 'padding' typo in the
short-read diagnostic message of erofs_dev_read().
Signed-off-by: Ajay Rajera <newajay.11r at gmail.com>
---
lib/io.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lib/io.c b/lib/io.c
index 0c5eb2c..583f52d 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -430,7 +430,7 @@ ssize_t erofs_dev_read(struct erofs_sb_info *sbi, int device_id,
if (read < 0)
return read;
if (read < len) {
- erofs_info("reach EOF of device @ %llu, pading with zeroes",
+ erofs_info("reach EOF of device @ %llu, padding with zeroes",
offset | 0ULL);
memset(buf + read, 0, len - read);
}
@@ -665,14 +665,15 @@ int erofs_io_xcopy(struct erofs_vfile *vout, off_t pos,
int ret = min_t(unsigned int, len, sizeof(buf));
ret = erofs_io_read(vin, buf, ret);
- if (ret < 0)
+ if (ret <= 0) {
+ if (!ret)
+ return -ENODATA;
return ret;
- if (ret > 0) {
- ret = erofs_io_pwrite(vout, buf, pos, ret);
- if (ret < 0)
- return ret;
- pos += ret;
}
+ ret = erofs_io_pwrite(vout, buf, pos, ret);
+ if (ret < 0)
+ return ret;
+ pos += ret;
len -= ret;
} while (len);
return 0;
--
2.51.0.windows.1
More information about the Linux-erofs
mailing list