[file-roller/gnome-3-8] libarchive: sanitize filenames before extracting
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller/gnome-3-8] libarchive: sanitize filenames before extracting
- Date: Tue, 2 Jul 2013 06:58:26 +0000 (UTC)
commit 65a1133fa47081bcbc800051af238197ef12fbf9
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon May 27 21:18:21 2013 +0200
libarchive: sanitize filenames before extracting
src/fr-archive-libarchive.c | 28 +++++++++++++++++++++-------
src/fr-window.c | 33 +++++++++++++++++++++------------
src/glib-utils.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/glib-utils.h | 4 ++++
4 files changed, 86 insertions(+), 19 deletions(-)
---
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 462232c..0817cf8 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -512,6 +512,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
const char *pathname;
char *fullpath;
+ const char *relative_path;
GFile *file;
GFile *parent;
GOutputStream *ostream;
@@ -531,7 +532,12 @@ extract_archive_thread (GSimpleAsyncResult *result,
}
fullpath = (*pathname == '/') ? g_strdup (pathname) : g_strconcat ("/", pathname, NULL);
- file = g_file_get_child (extract_data->destination, _g_path_get_relative_basename (fullpath,
extract_data->base_dir, extract_data->junk_paths));
+ relative_path = _g_path_get_relative_basename_safe (fullpath, extract_data->base_dir,
extract_data->junk_paths);
+ if (relative_path == NULL) {
+ archive_read_data_skip (a);
+ continue;
+ }
+ file = g_file_get_child (extract_data->destination, relative_path);
/* honor the skip_older and overwrite options */
@@ -615,14 +621,22 @@ extract_archive_thread (GSimpleAsyncResult *result,
linkname = archive_entry_hardlink (entry);
if (linkname != NULL) {
- char *link_fullpath;
- GFile *link_file;
- char *oldname;
- char *newname;
- int r;
+ char *link_fullpath;
+ const char *relative_path;
+ GFile *link_file;
+ char *oldname;
+ char *newname;
+ int r;
link_fullpath = (*linkname == '/') ? g_strdup (linkname) : g_strconcat ("/",
linkname, NULL);
- link_file = g_file_get_child (extract_data->destination,
_g_path_get_relative_basename (link_fullpath, extract_data->base_dir, extract_data->junk_paths));
+ relative_path = _g_path_get_relative_basename_safe (link_fullpath,
extract_data->base_dir, extract_data->junk_paths);
+ if (relative_path == NULL) {
+ g_free (link_fullpath);
+ archive_read_data_skip (a);
+ continue;
+ }
+
+ link_file = g_file_get_child (extract_data->destination, relative_path);
oldname = g_file_get_path (link_file);
newname = g_file_get_path (file);
diff --git a/src/fr-window.c b/src/fr-window.c
index a0f13fb..ba083a6 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -6639,26 +6639,35 @@ query_info_ready_for_overwrite_dialog_cb (GObject *source_object,
static void
_fr_window_ask_overwrite_dialog (OverwriteData *odata)
{
+ gboolean perform_extraction = TRUE;
+
if ((odata->edata->overwrite == FR_OVERWRITE_ASK) && (odata->current_file != NULL)) {
const char *base_name;
GFile *destination;
- base_name = _g_path_get_relative_basename ((char *) odata->current_file->data,
odata->edata->base_dir, odata->edata->junk_paths);
- destination = g_file_get_child (odata->edata->destination, base_name);
- g_file_query_info_async (destination,
- G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- G_PRIORITY_DEFAULT,
- odata->window->priv->cancellable,
- query_info_ready_for_overwrite_dialog_cb,
- odata);
+ base_name = _g_path_get_relative_basename_safe ((char *) odata->current_file->data,
odata->edata->base_dir, odata->edata->junk_paths);
+ if (base_name != NULL) {
+ destination = g_file_get_child (odata->edata->destination, base_name);
+ g_file_query_info_async (destination,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ odata->window->priv->cancellable,
+ query_info_ready_for_overwrite_dialog_cb,
+ odata);
- g_object_unref (destination);
+ g_object_unref (destination);
- return;
+ return;
+ }
+ else
+ perform_extraction = FALSE;
}
- if (odata->edata->file_list != NULL) {
+ if (odata->edata->file_list == NULL)
+ perform_extraction = FALSE;
+
+ if (perform_extraction) {
/* speed optimization: passing NULL when extracting all the
* files is faster if the command supports the
* propCanExtractAll property. */
diff --git a/src/glib-utils.c b/src/glib-utils.c
index 8f086d4..37d4648 100644
--- a/src/glib-utils.c
+++ b/src/glib-utils.c
@@ -1016,6 +1016,46 @@ _g_path_get_relative_basename (const char *path,
}
+#define ISDOT(c) ((c) == '.')
+#define ISSLASH(c) ((c) == '/')
+
+
+static const char *
+sanitize_filename (const char *file_name)
+{
+ size_t prefix_len;
+ char const *p;
+
+ prefix_len = 0;
+ for (p = file_name; *p; ) {
+ if (ISDOT (p[0]) && ISDOT (p[1]) && (ISSLASH (p[2]) || !p[2]))
+ prefix_len = p + 2 - file_name;
+
+ do {
+ char c = *p++;
+ if (ISSLASH (c))
+ break;
+ }
+ while (*p);
+ }
+
+ p = file_name + prefix_len;
+ while (ISSLASH (*p))
+ p++;
+
+ return p;
+}
+
+
+const char *
+_g_path_get_relative_basename_safe (const char *path,
+ const char *base_dir,
+ gboolean junk_paths)
+{
+ return sanitize_filename (_g_path_get_relative_basename (path, base_dir, junk_paths));
+}
+
+
gboolean
_g_filename_is_hidden (const gchar *name)
{
diff --git a/src/glib-utils.h b/src/glib-utils.h
index 64f4821..fef339c 100644
--- a/src/glib-utils.h
+++ b/src/glib-utils.h
@@ -145,6 +145,10 @@ gboolean _g_path_is_parent_of (const char *dirname
const char * _g_path_get_relative_basename (const char *path,
const char *base_dir,
gboolean junk_paths);
+const char * _g_path_get_relative_basename_safe
+ (const char *path,
+ const char *base_dir,
+ gboolean junk_paths);
gboolean _g_filename_is_hidden (const char *name);
const char * _g_filename_get_extension (const char *filename);
gboolean _g_filename_has_extension (const char *filename,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]