[gthumb] fixed crash when embedded data contains invalid utf8 values
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] fixed crash when embedded data contains invalid utf8 values
- Date: Sun, 2 Nov 2014 11:00:44 +0000 (UTC)
commit 43c7faef8bf5f5bcad826a1b83d7ad5c0ab5c004
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sun Nov 2 11:56:43 2014 +0100
fixed crash when embedded data contains invalid utf8 values
extensions/comments/gth-comment.c | 35 ++++++++++++++++++------
extensions/exiv2_tools/exiv2-utils.cpp | 21 ++++++++++++---
gthumb/dom.c | 46 +++++++++++++++++++++++++++----
gthumb/dom.h | 2 +
gthumb/glib-utils.c | 36 +++++++++++++++++++++++++
gthumb/glib-utils.h | 2 +
gthumb/gth-file-data.c | 3 +-
gthumb/gth-file-properties.c | 10 +++++--
gthumb/gth-string-list.c | 11 +++++++-
gthumb/gth-string-list.h | 3 ++
10 files changed, 145 insertions(+), 24 deletions(-)
---
diff --git a/extensions/comments/gth-comment.c b/extensions/comments/gth-comment.c
index e76e17d..8e22be0 100644
--- a/extensions/comments/gth-comment.c
+++ b/extensions/comments/gth-comment.c
@@ -638,8 +638,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::note");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
- gth_comment_set_note (comment, gth_metadata_get_formatted (metadata));
- write_comment = TRUE;
+ char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
+ if (value != NULL) {
+ gth_comment_set_note (comment, value);
+ g_free (value);
+ write_comment = TRUE;
+ }
}
}
@@ -647,8 +651,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::caption");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
- gth_comment_set_caption (comment, gth_metadata_get_formatted (metadata));
- write_comment = TRUE;
+ char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
+ if (value != NULL) {
+ gth_comment_set_caption (comment, value);
+ g_free (value);
+ write_comment = TRUE;
+ }
}
}
@@ -656,8 +664,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::place");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
- gth_comment_set_place (comment, gth_metadata_get_formatted (metadata));
- write_comment = TRUE;
+ char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
+ if (value != NULL) {
+ gth_comment_set_place (comment, value);
+ g_free (value);
+ write_comment = TRUE;
+ }
}
}
@@ -680,12 +692,17 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (categories != NULL) {
metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info,
"comment::categories");
comment_categories = gth_metadata_get_string_list (metadata);
- if (! gth_string_list_equal (categories, comment_categories)) {
+ if (! gth_string_list_equal_custom (categories, comment_categories, (GCompareFunc)
dom_str_find)) {
GList *scan;
gth_comment_clear_categories (comment);
- for (scan = gth_string_list_get_list (categories); scan; scan = scan->next)
- gth_comment_add_category (comment, scan->data);
+ for (scan = gth_string_list_get_list (categories); scan; scan = scan->next) {
+ char *value = _g_utf8_try_from_any (scan->data);
+ if (value != NULL) {
+ gth_comment_add_category (comment, value);
+ g_free (value);
+ }
+ }
write_comment = TRUE;
}
}
diff --git a/extensions/exiv2_tools/exiv2-utils.cpp b/extensions/exiv2_tools/exiv2-utils.cpp
index 4254ea2..70a1533 100644
--- a/extensions/exiv2_tools/exiv2-utils.cpp
+++ b/extensions/exiv2_tools/exiv2-utils.cpp
@@ -39,7 +39,7 @@
using namespace std;
-#define INVALID_VALUE "---"
+#define INVALID_VALUE N_("(invalid value)")
/* Some bits of information may be contained in more than one metadata tag.
@@ -451,6 +451,8 @@ set_attribute_from_metadata (GFileInfo *info,
char *formatted_value;
char *raw_value;
char *type_name;
+ char *formatted_value_utf8;
+ char *raw_value_utf8;
if (metadata == NULL)
return;
@@ -462,14 +464,19 @@ set_attribute_from_metadata (GFileInfo *info,
"value-type", &type_name,
NULL);
+ formatted_value_utf8 = _g_utf8_try_from_any (formatted_value);
+ raw_value_utf8 = _g_utf8_try_from_any (raw_value);
+
set_file_info (info,
attribute,
description,
- formatted_value,
- raw_value,
+ formatted_value_utf8,
+ raw_value_utf8,
NULL,
type_name);
+ g_free (raw_value_utf8);
+ g_free (formatted_value_utf8);
g_free (description);
g_free (formatted_value);
g_free (raw_value);
@@ -528,11 +535,16 @@ set_string_list_attribute_from_tagset (GFileInfo *info,
if (GTH_IS_METADATA (metadata) && (gth_metadata_get_data_type (GTH_METADATA (metadata)) !=
GTH_METADATA_TYPE_STRING_LIST)) {
char *raw;
+ char *utf8_raw;
char **keywords;
GthStringList *string_list;
g_object_get (metadata, "raw", &raw, NULL);
- keywords = g_strsplit (raw, ",", -1);
+ utf8_raw = _g_utf8_try_from_any (raw);
+ if (utf8_raw == NULL)
+ return;
+
+ keywords = g_strsplit (utf8_raw, ",", -1);
string_list = gth_string_list_new_from_strv (keywords);
metadata = (GObject *) gth_metadata_new_for_string_list (string_list);
g_file_info_set_attribute_object (info, attribute, metadata);
@@ -541,6 +553,7 @@ set_string_list_attribute_from_tagset (GFileInfo *info,
g_object_unref (string_list);
g_strfreev (keywords);
g_free (raw);
+ g_free (utf8_raw);
}
else
g_file_info_set_attribute_object (info, attribute, metadata);
diff --git a/gthumb/dom.c b/gthumb/dom.c
index a0b0c5a..4adb11b 100644
--- a/gthumb/dom.c
+++ b/gthumb/dom.c
@@ -71,7 +71,22 @@ _g_xml_attribute_quote (char *value)
g_return_val_if_fail (value != NULL, NULL);
- escaped = g_markup_escape_text (value, -1);
+ if (! g_utf8_validate (value, -1, NULL)) {
+ char *temp;
+
+ temp = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
+ if (temp == NULL)
+ temp = g_utf16_to_utf8 ((gunichar2 *) value, -1, NULL, NULL, NULL);
+
+ if (temp != NULL) {
+ escaped = g_markup_escape_text (temp, -1);
+ g_free (temp);
+ }
+ else
+ escaped = g_strdup (value);
+ }
+ else
+ escaped = g_markup_escape_text (value, -1);
dest = g_string_new ("\"");
for (p = escaped; (*p); p++) {
@@ -700,12 +715,20 @@ dom_domizable_load_from_element (DomDomizable *self,
/* GMarkupParser converts \r into \n, this function compares two strings
- * treating \r characters as they were equal to \n */
+ * treating \r characters as they were equal to \n. Furthermore treats invalid
+ * utf8 strings as null values. */
gboolean
dom_str_equal (const char *a,
const char *b)
{
const char *ai, *bi;
+ gboolean a_valid, b_valid;
+
+ if ((a != NULL) && ! g_utf8_validate (a, -1, NULL))
+ a = NULL;
+
+ if ((b != NULL) && ! g_utf8_validate (b, -1, NULL))
+ b = NULL;
if ((a == NULL) && (b == NULL))
return TRUE;
@@ -713,6 +736,9 @@ dom_str_equal (const char *a,
if ((a == NULL) || (b == NULL))
return FALSE;
+ if (g_utf8_collate (a, b) == 0)
+ return TRUE;
+
ai = a;
bi = b;
while ((*ai != '\0') && (*bi != '\0')) {
@@ -728,12 +754,12 @@ dom_str_equal (const char *a,
/* \r\n equal to \n */
if ((*ai == '\r') && (*(ai + 1) == '\n') && (*bi == '\n') && (*(bi + 1) != '\n'))
- ai++;
+ ai = g_utf8_next_char (ai);
if ((*bi == '\r') && (*(bi + 1) == '\n') && (*ai == '\n') && (*(ai + 1) != '\n'))
- ai++;
+ ai = g_utf8_next_char (ai);
}
- ai++;
- bi++;
+ ai = g_utf8_next_char (ai);
+ bi = g_utf8_next_char (bi);
}
/* 'end of string' equal to \n and to \r\n */
@@ -744,3 +770,11 @@ dom_str_equal (const char *a,
|| ((*ai == '\0') && (*bi == '\r') && (*(bi + 1) == '\n') && (*(bi + 2) == '\0'))
|| ((*bi == '\0') && (*ai == '\r') && (*(ai + 1) == '\n') && (*(ai + 2) == '\0')));
}
+
+
+int
+dom_str_find (const char *a,
+ const char *b)
+{
+ return dom_str_equal (a, b) ? 0 : -1;
+}
diff --git a/gthumb/dom.h b/gthumb/dom.h
index ebc7c50..69d33ef 100644
--- a/gthumb/dom.h
+++ b/gthumb/dom.h
@@ -187,6 +187,8 @@ void dom_domizable_load_from_element (DomDomizable *self,
gboolean dom_str_equal (const char *a,
const char *b);
+int dom_str_find (const char *a,
+ const char *b);
G_END_DECLS
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index 897413f..0225dcd 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -1029,6 +1029,42 @@ _g_utf8_remove_extension (const char *str)
}
+char *
+_g_utf8_try_from_any (const char *str)
+{
+ char *utf8_str;
+
+ if (str == NULL)
+ return NULL;
+
+ if (! g_utf8_validate (str, -1, NULL)) {
+ utf8_str = g_locale_to_utf8 (str, -1, NULL, NULL, NULL);
+ if (utf8_str == NULL)
+ utf8_str = g_utf16_to_utf8 ((gunichar2 *) str, -1, NULL, NULL, NULL);
+ }
+ else
+ utf8_str = g_strdup (str);
+
+ return utf8_str;
+}
+
+
+char *
+_g_utf8_from_any (const char *str)
+{
+ char *utf8_str;
+
+ if (str == NULL)
+ return NULL;
+
+ utf8_str = _g_utf8_try_from_any (str);
+ if (utf8_str == NULL)
+ utf8_str = g_strdup (_("(invalid value)"));
+
+ return utf8_str;
+}
+
+
static int
remove_from_file_list_and_get_position (GList **file_list,
GFile *file)
diff --git a/gthumb/glib-utils.h b/gthumb/glib-utils.h
index 3c3ee61..a7eb2d3 100644
--- a/gthumb/glib-utils.h
+++ b/gthumb/glib-utils.h
@@ -191,6 +191,8 @@ char ** _g_utf8_strsplit (const char *string,
char * _g_utf8_strstrip (const char *str);
gboolean _g_utf8_all_spaces (const char *utf8_string);
char * _g_utf8_remove_extension (const char *str);
+char * _g_utf8_try_from_any (const char *str);
+char * _g_utf8_from_any (const char *str);
GList * _g_list_insert_list_before (GList *list1,
GList *sibling,
GList *list2);
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index ebc4228..de447ae 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -526,8 +526,9 @@ char *
gth_file_data_get_attribute_as_string (GthFileData *file_data,
const char *id)
{
- char *value = NULL;
GObject *obj;
+ char *value = NULL;
+ char *utf8_value;
switch (g_file_info_get_attribute_type (file_data->info, id)) {
case G_FILE_ATTRIBUTE_TYPE_OBJECT:
diff --git a/gthumb/gth-file-properties.c b/gthumb/gth-file-properties.c
index 496dcff..cf70853 100644
--- a/gthumb/gth-file-properties.c
+++ b/gthumb/gth-file-properties.c
@@ -171,13 +171,17 @@ gth_file_properties_real_set_file (GthPropertyView *base,
}
if (value != NULL) {
+ char *utf8_value;
char *tmp_value;
- if (g_utf8_strlen (value, -1) > MAX_ATTRIBUTE_LENGTH)
- g_utf8_strncpy (g_utf8_offset_to_pointer (value, MAX_ATTRIBUTE_LENGTH - 1),
"…", 1);
- tmp_value = _g_utf8_replace (value, "[\r\n]", " ");
+ utf8_value = _g_utf8_from_any (value);
+ if (g_utf8_strlen (utf8_value, -1) > MAX_ATTRIBUTE_LENGTH)
+ g_utf8_strncpy (g_utf8_offset_to_pointer (utf8_value, MAX_ATTRIBUTE_LENGTH -
1), "…", 1);
+ tmp_value = _g_utf8_replace (utf8_value, "[\r\n]", " ");
g_free (value);
value = tmp_value;
+
+ g_free (utf8_value);
}
tooltip = g_markup_printf_escaped ("%s: %s", _(info->display_name), value);
diff --git a/gthumb/gth-string-list.c b/gthumb/gth-string-list.c
index 8c01062..ab1cb8d 100644
--- a/gthumb/gth-string-list.c
+++ b/gthumb/gth-string-list.c
@@ -149,6 +149,15 @@ gboolean
gth_string_list_equal (GthStringList *list1,
GthStringList *list2)
{
+ return gth_string_list_equal_custom (list1, list2, (GCompareFunc) strcmp);
+}
+
+
+gboolean
+gth_string_list_equal_custom (GthStringList *list1,
+ GthStringList *list2,
+ GCompareFunc compare_func)
+{
GList *keys1;
GList *keys2;
GList *scan;
@@ -165,7 +174,7 @@ gth_string_list_equal (GthStringList *list1,
return FALSE;
for (scan = keys1; scan; scan = scan->next)
- if (! g_list_find_custom (keys2, scan->data, (GCompareFunc) strcmp))
+ if (! g_list_find_custom (keys2, scan->data, compare_func))
return FALSE;
return TRUE;
diff --git a/gthumb/gth-string-list.h b/gthumb/gth-string-list.h
index cfb63f4..b9fd1f2 100644
--- a/gthumb/gth-string-list.h
+++ b/gthumb/gth-string-list.h
@@ -58,6 +58,9 @@ char * gth_string_list_join (GthStringList *list,
const char *separator);
gboolean gth_string_list_equal (GthStringList *list1,
GthStringList *list2);
+gboolean gth_string_list_equal_custom (GthStringList *list1,
+ GthStringList *list2,
+ GCompareFunc compare_func);
void gth_string_list_append (GthStringList *list1,
GthStringList *list2);
void gth_string_list_concat (GthStringList *list1,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]