The commit is required by the fix for CVE-2021-41072.
|
|
Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/9938154]
|
|
Signed-off-by: Kai Kang <kai.kang@windriver.com>
|
|
From 9938154174756ee48a94ea0b076397a2944b028d Mon Sep 17 00:00:00 2001
|
From: Phillip Lougher <phillip@squashfs.org.uk>
|
Date: Sun, 12 Sep 2021 22:58:11 +0100
|
Subject: [PATCH] unsquashfs: use linked list to store directory names
|
|
This should bring higher performance, and it allows sorting
|
if necessary (1.x and 2.0 filesystems).
|
|
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
|
---
|
squashfs-tools/unsquash-1.c | 30 +++++++++++++++---------------
|
squashfs-tools/unsquash-1234.c | 12 ++++++++----
|
squashfs-tools/unsquash-2.c | 29 +++++++++++++++--------------
|
squashfs-tools/unsquash-3.c | 29 +++++++++++++++--------------
|
squashfs-tools/unsquash-4.c | 29 +++++++++++++++--------------
|
squashfs-tools/unsquashfs.c | 16 ++++++++++------
|
squashfs-tools/unsquashfs.h | 3 ++-
|
7 files changed, 80 insertions(+), 68 deletions(-)
|
|
diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
|
index d0121c6..b604434 100644
|
--- a/squashfs-tools/unsquash-1.c
|
+++ b/squashfs-tools/unsquash-1.c
|
@@ -254,7 +254,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
long long start;
|
int bytes = 0;
|
int dir_count, size, res;
|
- struct dir_ent *new_dir;
|
+ struct dir_ent *ent, *cur_ent = NULL;
|
struct dir *dir;
|
|
TRACE("squashfs_opendir: inode start block %d, offset %d\n",
|
@@ -267,7 +267,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
MEM_ERROR();
|
|
dir->dir_count = 0;
|
- dir->cur_entry = 0;
|
+ dir->cur_entry = NULL;
|
dir->mode = (*i)->mode;
|
dir->uid = (*i)->uid;
|
dir->guid = (*i)->gid;
|
@@ -351,20 +351,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
"%d:%d, type %d\n", dire->name,
|
dirh.start_block, dire->offset, dire->type);
|
|
- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
|
- new_dir = realloc(dir->dirs, (dir->dir_count +
|
- DIR_ENT_SIZE) * sizeof(struct dir_ent));
|
- if(new_dir == NULL)
|
- MEM_ERROR();
|
-
|
- dir->dirs = new_dir;
|
- }
|
+ ent = malloc(sizeof(struct dir_ent));
|
+ if(ent == NULL)
|
+ MEM_ERROR();
|
|
- dir->dirs[dir->dir_count].name = strdup(dire->name);
|
- dir->dirs[dir->dir_count].start_block =
|
- dirh.start_block;
|
- dir->dirs[dir->dir_count].offset = dire->offset;
|
- dir->dirs[dir->dir_count].type = dire->type;
|
+ ent->name = strdup(dire->name);
|
+ ent->start_block = dirh.start_block;
|
+ ent->offset = dire->offset;
|
+ ent->type = dire->type;
|
+ ent->next = NULL;
|
+ if(cur_ent == NULL)
|
+ dir->dirs = ent;
|
+ else
|
+ cur_ent->next = ent;
|
+ cur_ent = ent;
|
dir->dir_count ++;
|
bytes += dire->size + 1;
|
}
|
diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
|
index ac46d9d..e389f8d 100644
|
--- a/squashfs-tools/unsquash-1234.c
|
+++ b/squashfs-tools/unsquash-1234.c
|
@@ -60,11 +60,15 @@ int check_name(char *name, int size)
|
|
void squashfs_closedir(struct dir *dir)
|
{
|
- int i;
|
+ struct dir_ent *ent = dir->dirs;
|
|
- for(i = 0; i < dir->dir_count; i++)
|
- free(dir->dirs[i].name);
|
+ while(ent) {
|
+ struct dir_ent *tmp = ent;
|
+
|
+ ent = ent->next;
|
+ free(tmp->name);
|
+ free(tmp);
|
+ }
|
|
- free(dir->dirs);
|
free(dir);
|
}
|
diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
|
index e847980..956f96f 100644
|
--- a/squashfs-tools/unsquash-2.c
|
+++ b/squashfs-tools/unsquash-2.c
|
@@ -347,7 +347,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
long long start;
|
int bytes = 0;
|
int dir_count, size, res;
|
- struct dir_ent *new_dir;
|
+ struct dir_ent *ent, *cur_ent = NULL;
|
struct dir *dir;
|
|
TRACE("squashfs_opendir: inode start block %d, offset %d\n",
|
@@ -360,7 +360,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
MEM_ERROR();
|
|
dir->dir_count = 0;
|
- dir->cur_entry = 0;
|
+ dir->cur_entry = NULL;
|
dir->mode = (*i)->mode;
|
dir->uid = (*i)->uid;
|
dir->guid = (*i)->gid;
|
@@ -444,19 +444,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
"%d:%d, type %d\n", dire->name,
|
dirh.start_block, dire->offset, dire->type);
|
|
- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
|
- new_dir = realloc(dir->dirs, (dir->dir_count +
|
- DIR_ENT_SIZE) * sizeof(struct dir_ent));
|
- if(new_dir == NULL)
|
- MEM_ERROR();
|
- dir->dirs = new_dir;
|
- }
|
+ ent = malloc(sizeof(struct dir_ent));
|
+ if(ent == NULL)
|
+ MEM_ERROR();
|
|
- dir->dirs[dir->dir_count].name = strdup(dire->name);
|
- dir->dirs[dir->dir_count].start_block =
|
- dirh.start_block;
|
- dir->dirs[dir->dir_count].offset = dire->offset;
|
- dir->dirs[dir->dir_count].type = dire->type;
|
+ ent->name = strdup(dire->name);
|
+ ent->start_block = dirh.start_block;
|
+ ent->offset = dire->offset;
|
+ ent->type = dire->type;
|
+ ent->next = NULL;
|
+ if(cur_ent == NULL)
|
+ dir->dirs = ent;
|
+ else
|
+ cur_ent->next = ent;
|
+ cur_ent = ent;
|
dir->dir_count ++;
|
bytes += dire->size + 1;
|
}
|
diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
|
index 8223f27..835a574 100644
|
--- a/squashfs-tools/unsquash-3.c
|
+++ b/squashfs-tools/unsquash-3.c
|
@@ -381,7 +381,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
long long start;
|
int bytes = 0;
|
int dir_count, size, res;
|
- struct dir_ent *new_dir;
|
+ struct dir_ent *ent, *cur_ent = NULL;
|
struct dir *dir;
|
|
TRACE("squashfs_opendir: inode start block %d, offset %d\n",
|
@@ -394,7 +394,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
MEM_ERROR();
|
|
dir->dir_count = 0;
|
- dir->cur_entry = 0;
|
+ dir->cur_entry = NULL;
|
dir->mode = (*i)->mode;
|
dir->uid = (*i)->uid;
|
dir->guid = (*i)->gid;
|
@@ -478,19 +478,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
"%d:%d, type %d\n", dire->name,
|
dirh.start_block, dire->offset, dire->type);
|
|
- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
|
- new_dir = realloc(dir->dirs, (dir->dir_count +
|
- DIR_ENT_SIZE) * sizeof(struct dir_ent));
|
- if(new_dir == NULL)
|
- MEM_ERROR();
|
- dir->dirs = new_dir;
|
- }
|
+ ent = malloc(sizeof(struct dir_ent));
|
+ if(ent == NULL)
|
+ MEM_ERROR();
|
|
- dir->dirs[dir->dir_count].name = strdup(dire->name);
|
- dir->dirs[dir->dir_count].start_block =
|
- dirh.start_block;
|
- dir->dirs[dir->dir_count].offset = dire->offset;
|
- dir->dirs[dir->dir_count].type = dire->type;
|
+ ent->name = strdup(dire->name);
|
+ ent->start_block = dirh.start_block;
|
+ ent->offset = dire->offset;
|
+ ent->type = dire->type;
|
+ ent->next = NULL;
|
+ if(cur_ent == NULL)
|
+ dir->dirs = ent;
|
+ else
|
+ cur_ent->next = ent;
|
+ cur_ent = ent;
|
dir->dir_count ++;
|
bytes += dire->size + 1;
|
}
|
diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
|
index 1e199a7..694783d 100644
|
--- a/squashfs-tools/unsquash-4.c
|
+++ b/squashfs-tools/unsquash-4.c
|
@@ -331,7 +331,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
|
long long start;
|
int bytes = 0, dir_count, size, res;
|
- struct dir_ent *new_dir;
|
+ struct dir_ent *ent, *cur_ent = NULL;
|
struct dir *dir;
|
|
TRACE("squashfs_opendir: inode start block %d, offset %d\n",
|
@@ -344,7 +344,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
MEM_ERROR();
|
|
dir->dir_count = 0;
|
- dir->cur_entry = 0;
|
+ dir->cur_entry = NULL;
|
dir->mode = (*i)->mode;
|
dir->uid = (*i)->uid;
|
dir->guid = (*i)->gid;
|
@@ -415,19 +415,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
|
"%d:%d, type %d\n", dire->name,
|
dirh.start_block, dire->offset, dire->type);
|
|
- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
|
- new_dir = realloc(dir->dirs, (dir->dir_count +
|
- DIR_ENT_SIZE) * sizeof(struct dir_ent));
|
- if(new_dir == NULL)
|
- MEM_ERROR();
|
- dir->dirs = new_dir;
|
- }
|
+ ent = malloc(sizeof(struct dir_ent));
|
+ if(ent == NULL)
|
+ MEM_ERROR();
|
|
- dir->dirs[dir->dir_count].name = strdup(dire->name);
|
- dir->dirs[dir->dir_count].start_block =
|
- dirh.start_block;
|
- dir->dirs[dir->dir_count].offset = dire->offset;
|
- dir->dirs[dir->dir_count].type = dire->type;
|
+ ent->name = strdup(dire->name);
|
+ ent->start_block = dirh.start_block;
|
+ ent->offset = dire->offset;
|
+ ent->type = dire->type;
|
+ ent->next = NULL;
|
+ if(cur_ent == NULL)
|
+ dir->dirs = ent;
|
+ else
|
+ cur_ent->next = ent;
|
+ cur_ent = ent;
|
dir->dir_count ++;
|
bytes += dire->size + 1;
|
}
|
diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c
|
index 04be53c..fee28ec 100644
|
--- a/squashfs-tools/unsquashfs.c
|
+++ b/squashfs-tools/unsquashfs.c
|
@@ -1337,14 +1337,18 @@ failed:
|
int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block,
|
unsigned int *offset, unsigned int *type)
|
{
|
- if(dir->cur_entry == dir->dir_count)
|
+ if(dir->cur_entry == NULL)
|
+ dir->cur_entry = dir->dirs;
|
+ else
|
+ dir->cur_entry = dir->cur_entry->next;
|
+
|
+ if(dir->cur_entry == NULL)
|
return FALSE;
|
|
- *name = dir->dirs[dir->cur_entry].name;
|
- *start_block = dir->dirs[dir->cur_entry].start_block;
|
- *offset = dir->dirs[dir->cur_entry].offset;
|
- *type = dir->dirs[dir->cur_entry].type;
|
- dir->cur_entry ++;
|
+ *name = dir->cur_entry->name;
|
+ *start_block = dir->cur_entry->start_block;
|
+ *offset = dir->cur_entry->offset;
|
+ *type = dir->cur_entry->type;
|
|
return TRUE;
|
}
|
diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
|
index 583fbe4..f8cf78c 100644
|
--- a/squashfs-tools/unsquashfs.h
|
+++ b/squashfs-tools/unsquashfs.h
|
@@ -168,17 +168,18 @@ struct dir_ent {
|
unsigned int start_block;
|
unsigned int offset;
|
unsigned int type;
|
+ struct dir_ent *next;
|
};
|
|
struct dir {
|
int dir_count;
|
- int cur_entry;
|
unsigned int mode;
|
uid_t uid;
|
gid_t guid;
|
unsigned int mtime;
|
unsigned int xattr;
|
struct dir_ent *dirs;
|
+ struct dir_ent *cur_entry;
|
};
|
|
struct file_entry {
|
--
|
2.17.1
|