[libgxps] Fixed crash in gxps_file_new()



commit d4bb8cede704e7e35c4c7339aff46ffbbd98a852
Author: Jason Crain <jason aquaticape us>
Date:   Tue Aug 2 00:15:47 2011 -0500

    Fixed crash in gxps_file_new()
    
    gxps_file_new() crashes when passed a directory or a nonexistant
    file.

 libgxps/gxps-archive.c |   96 +++++++++++++++++++++++++++++++++++++++++++-----
 libgxps/gxps-archive.h |    3 +-
 libgxps/gxps-file.c    |    6 ++-
 3 files changed, 93 insertions(+), 12 deletions(-)
---
diff --git a/libgxps/gxps-archive.c b/libgxps/gxps-archive.c
index 1508e51..b63efe2 100644
--- a/libgxps/gxps-archive.c
+++ b/libgxps/gxps-archive.c
@@ -25,18 +25,28 @@
 
 #include "gxps-archive.h"
 
+enum {
+	PROP_0,
+	PROP_FILE
+};
+
 struct _GXPSArchive {
 	GObject parent;
 
-	GFile  *filename;
-	GList  *entries;
+	gboolean  initialized;
+	GError   *init_error;
+	GFile    *filename;
+	GList    *entries;
 };
 
 struct _GXPSArchiveClass {
 	GObjectClass parent_class;
 };
 
-G_DEFINE_TYPE (GXPSArchive, gxps_archive, G_TYPE_OBJECT)
+static void initable_iface_init (GInitableIface *initable_iface);
+
+G_DEFINE_TYPE_WITH_CODE (GXPSArchive, gxps_archive, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
 
 #define BUFFER_SIZE 4096
 
@@ -112,7 +122,8 @@ _archive_close (struct archive *archive,
 {
 	ZipArchive *zip = (ZipArchive *)data;
 
-	g_object_unref (zip->stream);
+	if (zip->stream)
+		g_object_unref (zip->stream);
 	zip->stream = NULL;
 
 	return ARCHIVE_OK;
@@ -159,6 +170,8 @@ gxps_archive_finalize (GObject *object)
 		archive->filename = NULL;
 	}
 
+	g_clear_error (&archive->init_error);
+
 	G_OBJECT_CLASS (gxps_archive_parent_class)->finalize (object);
 }
 
@@ -169,25 +182,72 @@ gxps_archive_init (GXPSArchive *archive)
 }
 
 static void
+gxps_archive_set_property (GObject      *object,
+			   guint         prop_id,
+			   const GValue *value,
+			   GParamSpec   *pspec)
+{
+	GXPSArchive *archive = GXPS_ARCHIVE (object);
+
+	switch (prop_id) {
+	case PROP_FILE:
+		archive->filename = g_value_dup_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 gxps_archive_class_init (GXPSArchiveClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+	object_class->set_property = gxps_archive_set_property;
 	object_class->finalize = gxps_archive_finalize;
+
+	g_object_class_install_property (object_class,
+					 PROP_FILE,
+					 g_param_spec_object ("file",
+							      "File",
+							      "The archive file",
+							      G_TYPE_FILE,
+							      G_PARAM_WRITABLE |
+							      G_PARAM_CONSTRUCT_ONLY));
 }
 
-GXPSArchive *
-gxps_archive_new (GFile *filename)
+static gboolean
+gxps_archive_initable_init (GInitable     *initable,
+			    GCancellable  *cancellable,
+			    GError       **error)
 {
 	GXPSArchive          *archive;
 	ZipArchive           *zip;
 	struct archive_entry *entry;
 	gint                  result;
 
-	archive = GXPS_ARCHIVE (g_object_new (GXPS_TYPE_ARCHIVE, NULL));
-	archive->filename = g_object_ref (filename);
+	archive = GXPS_ARCHIVE (initable);
+
+	if (archive->initialized) {
+		if (archive->init_error) {
+			g_propagate_error (error, g_error_copy (archive->init_error));
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	archive->initialized = TRUE;
+
+	zip = gxps_zip_archive_create (archive->filename);
+	if (zip->error) {
+		g_propagate_error (&archive->init_error, zip->error);
+		g_propagate_error (error, g_error_copy (archive->init_error));
+		gxps_zip_archive_destroy (zip);
+		return FALSE;
+	}
 
-	zip = gxps_zip_archive_create (filename);
 	do {
 		result = archive_read_next_header (zip->archive, &entry);
 		if (result >= ARCHIVE_WARN && result <= ARCHIVE_OK) {
@@ -205,7 +265,23 @@ gxps_archive_new (GFile *filename)
 
 	gxps_zip_archive_destroy (zip);
 
-	return archive;
+	return TRUE;
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+	initable_iface->init = gxps_archive_initable_init;
+}
+
+GXPSArchive *
+gxps_archive_new (GFile   *filename,
+		  GError **error)
+{
+	return g_initable_new (GXPS_TYPE_ARCHIVE,
+			       NULL, error,
+			       "file", filename,
+			       NULL);
 }
 
 gboolean
diff --git a/libgxps/gxps-archive.h b/libgxps/gxps-archive.h
index 05edc6b..62226db 100644
--- a/libgxps/gxps-archive.h
+++ b/libgxps/gxps-archive.h
@@ -38,7 +38,8 @@ typedef struct _GXPSArchiveClass GXPSArchiveClass;
 typedef struct _GXPSArchiveEntry GXPSArchiveEntry;
 
 GType             gxps_archive_get_type       (void) G_GNUC_CONST;
-GXPSArchive      *gxps_archive_new            (GFile            *filename);
+GXPSArchive      *gxps_archive_new            (GFile            *filename,
+					       GError          **error);
 
 gboolean          gxps_archive_has_entry      (GXPSArchive      *archive,
 					       const gchar      *path);
diff --git a/libgxps/gxps-file.c b/libgxps/gxps-file.c
index 02af1b2..10002e6 100644
--- a/libgxps/gxps-file.c
+++ b/libgxps/gxps-file.c
@@ -316,7 +316,11 @@ gxps_file_initable_init (GInitable     *initable,
 
 	xps->priv->initialized = TRUE;
 
-	xps->priv->zip = gxps_archive_new (xps->priv->file);
+	xps->priv->zip = gxps_archive_new (xps->priv->file, &xps->priv->init_error);
+	if (!xps->priv->zip) {
+		g_propagate_error (error, g_error_copy (xps->priv->init_error));
+		return FALSE;
+	}
 
 	if (!gxps_file_parse_rels (xps, &xps->priv->init_error)) {
 		g_propagate_error (error, g_error_copy (xps->priv->init_error));



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