[PATCH 2/2] erofs-utils: tar: handle empty values in pax extended headers

Gao Xiang <[email protected]>
Newsgroups org.ozlabs.lists.linux-erofs
Message-ID <[email protected]>
As POSIX pax(1) [1] says,

If the <value> field is zero length, it shall delete any header block
field, previously entered extended header value, or global extended
header value of the same name.

Note that extended attribute removal is not implemented yet.

[1] https://pubs.opengroup.org/onlinepubs/009695399/utilities/pax.html
Signed-off-by: Gao Xiang <[email protected]>
---
 lib/tar.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/lib/tar.c b/lib/tar.c
index c522bc3f21e1..9e53af511c0c 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -487,7 +487,7 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 
 	while (p < buf + size) {
 		char *kv, *key, *value;
-		int len, n;
+		int len, n, j;
 		/* extended records are of the format: "LEN NAME=VALUE\n" */
 		ret = sscanf(p, "%d %n", &len, &n);
 		if (ret < 1 || len <= n || len > buf + size - p) {
@@ -514,20 +514,25 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 			value++;
 
 			if (!strncmp(kv, "path=", sizeof("path=") - 1)) {
-				int j = p - 1 - value;
 				free(eh->path);
+				if (!*value) {
+					eh->path = NULL;
+					continue;
+				}
+				j = p - 1 - value;
 				eh->path = strdup(value);
 				while (j && eh->path[j - 1] == '/')
 					eh->path[--j] = '\0';
 			} else if (!strncmp(kv, "linkpath=",
 					sizeof("linkpath=") - 1)) {
 				free(eh->link);
-				eh->link = strdup(value);
+				eh->link = *value ? strdup(value) : NULL;
 			} else if (!strncmp(kv, "mtime=",
 					sizeof("mtime=") - 1)) {
-				unsigned int ns = 0;
-				int digits = 0;
-
+				if (!*value) {
+					eh->use_mtime = false;
+					continue;
+				}
 				ret = sscanf(value, "%lld %n", &lln, &n);
 				if(ret < 1) {
 					ret = -EIO;
@@ -535,6 +540,9 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 				}
 				eh->st.st_mtime = lln;
 				if (value[n] == '.') {
+					unsigned int ns = 0;
+					int digits = 0;
+
 					while (value[n + 1] >= '0' &&
 					       value[n + 1] <= '9') {
 						if (digits < 9)
@@ -566,6 +574,10 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 				eh->use_mtime = true;
 			} else if (!strncmp(kv, "size=",
 					sizeof("size=") - 1)) {
+				if (!*value) {
+					eh->use_size = false;
+					continue;
+				}
 				ret = sscanf(value, "%lld %n", &lln, &n);
 				if(ret < 1 || value[n] != '\0') {
 					ret = -EIO;
@@ -580,6 +592,10 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 				eh->st.st_size = lln;
 				eh->use_size = true;
 			} else if (!strncmp(kv, "uid=", sizeof("uid=") - 1)) {
+				if (!*value) {
+					eh->use_uid = false;
+					continue;
+				}
 				ret = sscanf(value, "%lld %n", &lln, &n);
 				if(ret < 1 || value[n] != '\0') {
 					ret = -EIO;
@@ -588,6 +604,10 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
 				eh->st.st_uid = lln;
 				eh->use_uid = true;
 			} else if (!strncmp(kv, "gid=", sizeof("gid=") - 1)) {
+				if (!*value) {
+					eh->use_gid = false;
+					continue;
+				}
 				ret = sscanf(value, "%lld %n", &lln, &n);
 				if(ret < 1 || value[n] != '\0') {
 					ret = -EIO;
-- 
2.43.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.