[nautilus-actions] Fix coredump when trying to import an empty file by DnD



commit 90e837ee8201d89654b0ad81d35f4957af04a48e
Author: Pierre Wieser <pwieser trychlos org>
Date:   Tue Dec 6 23:10:25 2011 +0100

    Fix coredump when trying to import an empty file by DnD

 ChangeLog                          |   16 +++++
 po/POTFILES.in                     |    1 +
 src/api/na-core-utils.h            |    1 +
 src/api/na-iimporter.h             |    7 ++-
 src/core/na-core-utils.c           |  109 +++++++++++++++++++++++++++++++++++-
 src/core/na-importer.c             |   16 +++++-
 src/io-desktop/nadp-desktop-file.c |   10 +++-
 src/io-desktop/nadp-reader.c       |    5 ++
 src/io-xml/naxml-reader.c          |   12 +++-
 9 files changed, 168 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8bab8df..047d678 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2011-12-06 Pierre Wieser <pwieser trychlos org>
 
+	Fix a coredump when trying to import an empty file by DnD.
+	Extend the fix by checking the size and the type of the candidate.
+
+	* src/api/na-core-utils.h:
+	* src/core/na-core-utils.c (na_core_utils_file_is_loadable): New function.
+
+	* src/api/na-iimporter.h (IMPORTER_CODE_NOT_LOADABLE): New return code.
+
+	* src/core/na-importer.c (import_from_uri):
+	Do not try other modules one the first detects that a file is not loadable.
+
+	* src/io-desktop/nadp-desktop-file.c (nadp_desktop_file_new_from_uri):
+	* src/io-desktop/nadp-reader.c (nadp_reader_iimporter_import_from_uri):
+	* src/io-xml/naxml-reader.c (naxml_reader_import_from_uri):
+	Check whether the file is loadable before trying to import it.
+
 	* src/nact/nact-main-tab.h:
 	* src/nact/nact-main-window.h: Fix comments.
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c9c099b..ba302fb 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,7 @@ src/core/na-about.c
 src/core/na-desktop-environment.c
 src/core/na-icontext-factory.c
 src/core/na-iimporter.c
+src/core/na-importer.c
 src/core/na-importer-ask.c
 [type: gettext/glade] src/core/na-importer-ask.ui
 src/core/na-io-provider.c
diff --git a/src/api/na-core-utils.h b/src/api/na-core-utils.h
index 0167751..f9bbcb4 100644
--- a/src/api/na-core-utils.h
+++ b/src/api/na-core-utils.h
@@ -91,6 +91,7 @@ void     na_core_utils_dir_split_ext( const gchar *string, gchar **first, gchar
  */
 gboolean na_core_utils_file_delete       ( const gchar *path );
 gboolean na_core_utils_file_exists       ( const gchar *uri );
+gboolean na_core_utils_file_is_loadable  ( const gchar *uri );
 gchar   *na_core_utils_file_load_from_uri( const gchar *uri, gsize *length );
 
 /* miscellaneous
diff --git a/src/api/na-iimporter.h b/src/api/na-iimporter.h
index a5f284b..81974d6 100644
--- a/src/api/na-iimporter.h
+++ b/src/api/na-iimporter.h
@@ -159,6 +159,10 @@ typedef enum {
  * @IMPORTER_CODE_NO_ITEM_TYPE:      item type not found.
  * @IMPORTER_CODE_UNKNOWN_ITEM_TYPE: unknown item type.
  * @IMPORTER_CODE_CANCELLED:         operation cancelled by the user.
+ * @IMPORTER_CODE_NOT_LOADABLE:      the file is considered as not loadable at all.
+ *                                   This is not a matter of which I/O provider has been tried,
+ *                                   but the file is empty, or too big, or eventually not a
+ *                                   regular file.
  *
  * Define the return status of an import operation.
  */
@@ -169,7 +173,8 @@ typedef enum {
 	IMPORTER_CODE_NO_ITEM_ID,
 	IMPORTER_CODE_NO_ITEM_TYPE,
 	IMPORTER_CODE_UNKNOWN_ITEM_TYPE,
-	IMPORTER_CODE_CANCELLED
+	IMPORTER_CODE_CANCELLED,
+	IMPORTER_CODE_NOT_LOADABLE
 }
 	NAIImporterImportStatus;
 
diff --git a/src/core/na-core-utils.c b/src/core/na-core-utils.c
index 6277a1f..e71ea3b 100644
--- a/src/core/na-core-utils.c
+++ b/src/core/na-core-utils.c
@@ -43,8 +43,15 @@
 
 #include "na-about.h"
 
+/* minimal and maximal size for loading the content of a file in memory
+ * used by na_core_utils_file_is_size_ok()
+ */
+#define SIZE_MIN		  1
+#define SIZE_MAX	1048576		/* 1 MB */
+
 static GSList  *text_to_string_list( const gchar *text, const gchar *separator, const gchar *default_value );
 static gboolean info_dir_is_writable( GFile *file, const gchar *path );
+static gboolean file_is_loadable( GFile *file );
 
 /**
  * na_core_utils_boolean_from_string
@@ -1002,6 +1009,92 @@ na_core_utils_file_exists( const gchar *uri )
 }
 
 /**
+ * na_core_utils_file_is_loadable:
+ * @uri: the URI to be checked.
+ *
+ * Checks that the file is suitable to be loaded in memory, because
+ * it is not empty, and its size is reasonable (less than 1MB).
+ * Also checks that a file is a regular file (or a symlink to a
+ * regular file).
+ *
+ * Returns: whether the file is suitable to be loaded in memory.
+ *
+ * Since: 3.1
+ */
+gboolean
+na_core_utils_file_is_loadable( const gchar *uri )
+{
+	static const gchar *thisfn = "na_core_utils_file_is_loadable";
+	GFile *file;
+	gboolean isok;
+
+	g_debug( "%s: uri=%s", thisfn, uri );
+
+	isok = FALSE;
+	file = g_file_new_for_uri( uri );
+
+	isok = file_is_loadable( file );
+
+	g_object_unref( file );
+
+	return( isok );
+}
+
+static gboolean
+file_is_loadable( GFile *file )
+{
+	static const gchar *thisfn = "na_core_utils_file_is_loadable";
+	GError *error;
+	GFileInfo *info;
+	guint64 size;
+	GFileType type;
+	gboolean isok;
+	GFile *target_file;
+
+	error = NULL;
+	isok = FALSE;
+	info = g_file_query_info( file,
+			G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
+			G_FILE_QUERY_INFO_NONE, NULL, &error );
+
+	if( !info ){
+		if( error ){
+			g_debug( "%s: %s", thisfn, error->message );
+			g_error_free( error );
+		}
+
+	} else {
+		size = g_file_info_get_attribute_uint64( info, G_FILE_ATTRIBUTE_STANDARD_SIZE );
+		g_debug( "%s: size=%lu", thisfn, ( unsigned long ) size );
+		isok = ( size >= SIZE_MIN && size <= SIZE_MAX );
+	}
+
+	if( isok ){
+		type = g_file_info_get_file_type( info );
+		g_debug( "%s: type=%u", thisfn, ( unsigned ) type );
+
+		if( type != G_FILE_TYPE_REGULAR ){
+			isok = FALSE;
+
+			if( type == G_FILE_TYPE_SYMBOLIC_LINK ){
+				const char *target = g_file_info_get_symlink_target( info );
+				if( target && strlen( target )){
+					target_file = g_file_resolve_relative_path( file, target );
+					if( target_file ){
+						isok = file_is_loadable( target_file );
+						g_object_unref( target_file );
+					}
+				}
+			}
+		}
+	}
+
+	g_object_unref( info );
+
+	return( isok );
+}
+
+/**
  * na_core_utils_file_load_from_uri:
  * @uri: the URI the file must be loaded from.
  * @length: a pointer to the length of the read content.
@@ -1017,17 +1110,31 @@ na_core_utils_file_exists( const gchar *uri )
 gchar *
 na_core_utils_file_load_from_uri( const gchar *uri, gsize *length )
 {
+	static const gchar *thisfn = "na_core_utils_file_load_from_uri";
 	gchar *data;
 	GFile *file;
+	GError *error;
+
+	g_debug( "%s: uri=%s, length=%p", thisfn, uri, ( void * ) length );
+
+	error = NULL;
+	data = NULL;
+	if( length ){
+		*length = 0;
+	}
 
 	file = g_file_new_for_uri( uri );
 
-	if( !g_file_load_contents( file, NULL, &data, length, NULL, NULL )){
+	if( !g_file_load_contents( file, NULL, &data, length, NULL, &error )){
 		g_free( data );
 		data = NULL;
 		if( length ){
 			*length = 0;
 		}
+		if( error ){
+			g_debug( "%s: %s", thisfn, error->message );
+			g_error_free( error );
+		}
 	}
 
 	g_object_unref( file );
diff --git a/src/core/na-importer.c b/src/core/na-importer.c
index 8c23938..0bebb9e 100644
--- a/src/core/na-importer.c
+++ b/src/core/na-importer.c
@@ -32,6 +32,7 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
 #include <string.h>
 
 #include <api/na-core-utils.h>
@@ -55,6 +56,9 @@ static guint         import_from_uri( const NAPivot *pivot, GList *modules, NAIm
 static NAObjectItem *is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *parms );
 static guint         ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms );
 
+/* i18n: '%s' stands for the file URI */
+#define ERR_NOT_LOADABLE	_( "%s is not loadable (empty or too big or not a regular file)" )
+
 /*
  * na_importer_import_from_list:
  * @pivot: the #NAPivot pivot for this application.
@@ -177,13 +181,23 @@ import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, c
 
 	all_messages = NULL;
 
-	for( im = modules ; im && code == IMPORTER_CODE_NOT_WILLING_TO ; im = im->next ){
+	for( im = modules ;
+			im && ( code == IMPORTER_CODE_NOT_WILLING_TO || code == IMPORTER_CODE_NOT_LOADABLE ) ;
+			im = im->next ){
+
 		code = na_iimporter_import_from_uri( NA_IIMPORTER( im->data ), &provider_parms );
 
 		if( code == IMPORTER_CODE_NOT_WILLING_TO ){
 			all_messages = g_slist_concat( all_messages, provider_parms.messages );
 			provider_parms.messages = NULL;
 
+		} else if( code == IMPORTER_CODE_NOT_LOADABLE ){
+			na_core_utils_slist_free( all_messages );
+			all_messages = NULL;
+			na_core_utils_slist_free( provider_parms.messages );
+			provider_parms.messages = NULL;
+			na_core_utils_slist_add_message( &all_messages, ERR_NOT_LOADABLE, ( const gchar * ) uri );
+
 		} else {
 			na_core_utils_slist_free( all_messages );
 			all_messages = provider_parms.messages;
diff --git a/src/io-desktop/nadp-desktop-file.c b/src/io-desktop/nadp-desktop-file.c
index 50d83c0..411b454 100644
--- a/src/io-desktop/nadp-desktop-file.c
+++ b/src/io-desktop/nadp-desktop-file.c
@@ -279,12 +279,18 @@ nadp_desktop_file_new_from_uri( const gchar *uri )
 	gsize length;
 
 	ndf = NULL;
+	data = NULL;
+	length = 0;
+
 	g_debug( "%s: uri=%s", thisfn, uri );
 	g_return_val_if_fail( uri && g_utf8_strlen( uri, -1 ), ndf );
 
 	data = na_core_utils_file_load_from_uri( uri, &length );
-	if( !length ){
-		g_debug( "%s: file is empty", thisfn );
+	g_debug( "%s: length=%lu", thisfn, ( unsigned long ) length );
+
+	/* normally, length and data should be both NULL or both not NULL
+	 */
+	if( !length || !data ){
 		return( NULL );
 	}
 
diff --git a/src/io-desktop/nadp-reader.c b/src/io-desktop/nadp-reader.c
index b2d99fb..2d26c69 100644
--- a/src/io-desktop/nadp-reader.c
+++ b/src/io-desktop/nadp-reader.c
@@ -368,6 +368,11 @@ nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterI
 	g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
 	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
 
+	if( !na_core_utils_file_is_loadable( parms->uri )){
+		code = IMPORTER_CODE_NOT_LOADABLE;
+		return( code );
+	}
+
 	code = IMPORTER_CODE_NOT_WILLING_TO;
 
 	ndf = nadp_desktop_file_new_from_uri( parms->uri );
diff --git a/src/io-xml/naxml-reader.c b/src/io-xml/naxml-reader.c
index a07d060..d3f51db 100644
--- a/src/io-xml/naxml-reader.c
+++ b/src/io-xml/naxml-reader.c
@@ -329,14 +329,18 @@ naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFrom
 
 	g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
 
-	reader = reader_new();
-	reader->private->importer = ( NAIImporter * ) instance;
-	reader->private->parms = parms;
-
 	parms->exist = FALSE;
 	parms->import_mode = IMPORTER_MODE_NO_IMPORT;
 	parms->imported = NULL;
 
+	if( !na_core_utils_file_is_loadable( parms->uri )){
+		return( IMPORTER_CODE_NOT_LOADABLE );
+	}
+
+	reader = reader_new();
+	reader->private->importer = ( NAIImporter * ) instance;
+	reader->private->parms = parms;
+
 	code = reader_parse_xmldoc( reader );
 
 	if( code == IMPORTER_CODE_NOT_WILLING_TO ){



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]