[PATCH 2/4] Allocate memory for and truncate strings that go into the title bar

Lubomir I. Ivanov neolit123 at gmail.com
Wed Oct 17 14:43:48 PDT 2012


From: "Lubomir I. Ivanov" <neolit123 at gmail.com>

info.c:show_dive_info() uses buffers of 80 char, which might not be enough
for all unicode strings to fit. The function snprintf() can be used to
truncate a string to the maximum buffer length, however this should
not be used with unicode strings, since it can split the bytes of a
wide char, causing some corruption.

Instead of a fixed buffer we now allocate/free memory for the title text and
attempt to more safely truncate user entered text by using g_utf8_strlen()
and g_utf8_strncpy(). Long unicode filenames still remain a responsibility
of the user, but they should be now safe as well. On the other hand the string
formed by the function divename() and the variable maxlen should be
monitored by developers to accommodate all translations.

Signed-off-by: Lubomir I. Ivanov <neolit123 at gmail.com>
---
 info.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/info.c b/info.c
index b59b899..687f83d 100644
--- a/info.c
+++ b/info.c
@@ -114,17 +114,26 @@ static int divename(char *buf, size_t size, struct dive *dive)
 
 void show_dive_info(struct dive *dive)
 {
+	const char *subs = "Subsurface: ";
 	const char *text;
-	char buffer[80];
-	char title[80];
+	const int maxlen = 128;
 	char *basename;
+	char *title;
+	char *buffer = NULL;
+	int len1, len2, sz;
 
 	if (!dive) {
 		if (existing_filename) {
 			basename = g_path_get_basename(existing_filename);
-			snprintf(title, 80, "Subsurface: %s", basename);
-			free(basename);
+			len1 = strlen(subs);
+			len2 = g_utf8_strlen(basename, -1);
+			sz = (len1 + len2 + 1) * sizeof(gunichar);
+			title = malloc(sz);
+			strncpy(title, subs, len1);
+			g_utf8_strncpy(title + len1, basename, len2);
 			gtk_window_set_title(GTK_WINDOW(main_window), title);
+			free(basename);
+			free(title);
 		} else {
 			gtk_window_set_title(GTK_WINDOW(main_window), "Subsurface");
 		}
@@ -143,23 +152,40 @@ void show_dive_info(struct dive *dive)
 		text = "";
 	if (*text) {
 		if (dive->number) {
-			snprintf(buffer, sizeof(buffer), _("Dive #%d - %s"), dive->number, text);
+			len1 = g_utf8_strlen(text, -1);
+			sz = (len1 + 32) * sizeof(gunichar);
+			buffer = malloc(sz);
+			snprintf(buffer, sz, _("Dive #%d - "), dive->number);
+			g_utf8_strncpy(buffer + strlen(buffer), text, len1);
 			text = buffer;
 		}
 	} else {
-		divename(buffer, sizeof(buffer), dive);
+		sz = (maxlen + 32) * sizeof(gunichar);
+		buffer = malloc(sz);
+		divename(buffer, sz, dive);
 		text = buffer;
 	}
 
 	/* put it all together */
 	if (existing_filename) {
 		basename = g_path_get_basename(existing_filename);
-		snprintf(title, 80, "%s: %s", basename, text);
-		free(basename);
+		len1 = g_utf8_strlen(basename, -1);
+		len2 = g_utf8_strlen(text, -1);
+		if (len2 > maxlen)
+			len2 = maxlen;
+		sz = (len1 + len2 + 3) * sizeof(gunichar); /* reserver space for ": " */
+		title = malloc(sz);
+		g_utf8_strncpy(title, basename, len1);
+		strncpy(title + strlen(basename), (const char *)": ", 2);
+		g_utf8_strncpy(title + strlen(basename) + 2, text, len2);
 		gtk_window_set_title(GTK_WINDOW(main_window), title);
+		free(basename);
+		free(title);
 	} else {
 		gtk_window_set_title(GTK_WINDOW(main_window), text);
 	}
+	if (buffer)
+		free(buffer);
 	SET_TEXT_VALUE(divemaster);
 	SET_TEXT_VALUE(buddy);
 	SET_TEXT_VALUE(location);
-- 
1.7.11.msysgit.0



More information about the subsurface mailing list