[PATCH] erofs-utils: lib: tar: fix fractional PAX mtime parsing
Vansh Choudhary
ch at vnsh.in
Mon Mar 30 04:36:39 AEDT 2026
The fractional part of PAX mtime values was parsed as a plain integer,
so "123.5" ended up with 5ns instead of 500000000ns.
Scale the fractional part according to its decimal width before storing
it as nanoseconds. Also normalize negative fractional timestamps and
reject malformed mtime values with missing digits or trailing junk.
Fixes: 95d315fd7958 ("erofs-utils: introduce tarerofs")
Signed-off-by: Vansh Choudhary <ch at vnsh.in>
---
lib/tar.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/lib/tar.c b/lib/tar.c
index 4eb0060..4e97522 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -2,6 +2,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <sys/stat.h>
#include "erofs/print.h"
#include "erofs/diskbuf.h"
@@ -525,6 +526,9 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
eh->link = strdup(value);
} else if (!strncmp(kv, "mtime=",
sizeof("mtime=") - 1)) {
+ unsigned int ns = 0;
+ int digits = 0;
+
ret = sscanf(value, "%lld %n", &lln, &n);
if(ret < 1) {
ret = -EIO;
@@ -532,12 +536,31 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
}
eh->st.st_mtime = lln;
if (value[n] == '.') {
- ret = sscanf(value + n + 1, "%d", &n);
- if (ret < 1) {
+ while (value[n + 1] >= '0' &&
+ value[n + 1] <= '9') {
+ if (digits < 9)
+ ns = ns * 10 + value[n + 1] - '0';
+ ++digits;
+ ++n;
+ }
+ if (!digits || value[n + 1] != '\0') {
ret = -EIO;
goto out;
}
- ST_MTIM_NSEC_SET(&eh->st, n);
+ while (digits++ < 9)
+ ns *= 10;
+ if (ns && value[0] == '-') {
+ if (eh->st.st_mtime == LLONG_MIN) {
+ ret = -EIO;
+ goto out;
+ }
+ --eh->st.st_mtime;
+ ns = 1000000000 - ns;
+ }
+ ST_MTIM_NSEC_SET(&eh->st, ns);
+ } else if (value[n] != '\0') {
+ ret = -EIO;
+ goto out;
} else {
ST_MTIM_NSEC_SET(&eh->st, 0);
}
--
2.43.0
More information about the Linux-erofs
mailing list