/pidgin/main: 9a2250c4e9d1: Fix Coverity TOCTOU warnings

Tomasz Wasilczyk <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 9a2250c4e9d17b409133dda9a6074914094dcade
Author:	 Tomasz Wasilczyk <[email protected]>
Date:	 2014-05-12 23:55 +0200
Branch:	 release-2.x.y
URL: https://hg.pidgin.im/pidgin/main/rev/9a2250c4e9d1

Description:

Fix Coverity TOCTOU warnings

diffstat:

 libpurple/log.c                 |  25 +++++-----
 libpurple/protocols/silc/util.c |  95 +++++++++-------------------------------
 libpurple/util.c                |   7 ++-
 3 files changed, 42 insertions(+), 85 deletions(-)

diffs (213 lines):

diff --git a/libpurple/log.c b/libpurple/log.c
--- a/libpurple/log.c
+++ b/libpurple/log.c
@@ -1676,7 +1676,7 @@ static GList *old_logger_list(PurpleLogT
 	time_t log_last_modified;
 	FILE *index;
 	FILE *file;
-	int index_fd;
+	int file_fd, index_fd;
 	char *index_tmp;
 	char buf[BUF_LONG];
 	struct tm tm;
@@ -1692,13 +1692,21 @@ static GList *old_logger_list(PurpleLogT
 
 	g_free(logfile);
 
-	if (g_stat(purple_stringref_value(pathref), &st))
-	{
+	file_fd = g_open(purple_stringref_value(pathref), 0, O_RDONLY);
+	if (file_fd == -1 || (file = fdopen(file_fd, "rb")) == NULL) {
+		purple_debug_error("log",
+			"Failed to open log file \"%s\" for reading: %s\n",
+			purple_stringref_value(pathref), g_strerror(errno));
 		purple_stringref_unref(pathref);
 		g_free(pathstr);
 		return NULL;
 	}
-	else
+	if (fstat(file_fd, &st) == -1) {
+		purple_stringref_unref(pathref);
+		g_free(pathstr);
+		fclose(file);
+		return NULL;
+	} else
 		log_last_modified = st.st_mtime;
 
 	/* Change the .log extension to .idx */
@@ -1752,19 +1760,12 @@ static GList *old_logger_list(PurpleLogT
 				fclose(index);
 				purple_stringref_unref(pathref);
 
+				fclose(file);
 				return list;
 			}
 		}
 	}
 
-	if (!(file = g_fopen(purple_stringref_value(pathref), "rb"))) {
-		purple_debug_error("log", "Failed to open log file \"%s\" for reading: %s\n",
-		                   purple_stringref_value(pathref), g_strerror(errno));
-		purple_stringref_unref(pathref);
-		g_free(pathstr);
-		return NULL;
-	}
-
 	index_tmp = g_strdup_printf("%s.XXXXXX", pathstr);
 	if ((index_fd = g_mkstemp(index_tmp)) == -1) {
 		purple_debug_error("log", "Failed to open index temp file: %s\n",
diff --git a/libpurple/protocols/silc/util.c b/libpurple/protocols/silc/util.c
--- a/libpurple/protocols/silc/util.c
+++ b/libpurple/protocols/silc/util.c
@@ -92,104 +92,55 @@ gboolean silcpurple_check_silc_dir(Purpl
 	g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
 		   silcpurple_silcdir());
 
+	if (pw->pw_uid != geteuid()) {
+		purple_debug_error("silc", "Couldn't create directories due to wrong uid!\n");
+		return FALSE;
+	}
+
 	/*
 	 * Check ~/.silc directory
 	 */
+	if (g_mkdir(filename, 0755) != 0 && errno != EEXIST) {
+		purple_debug_error("silc", "Couldn't create '%s' directory\n", filename);
+		return FALSE;
+	}
+
+#ifndef _WIN32
 	if ((g_stat(filename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(filename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", filename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					filename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno));
-			return FALSE;
-		}
+		purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno));
+		return FALSE;
 	} else {
-#ifndef _WIN32
 		/* Check the owner of the dir */
 		if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
 			purple_debug_error("silc", "You don't seem to own '%s' directory\n",
 				filename);
 			return FALSE;
 		}
+	}
 #endif
-	}
 
 	/*
 	 * Check ~./silc/serverkeys directory
 	 */
-	if ((g_stat(servfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(servfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					servfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 servfilename, g_strerror(errno));
-			return FALSE;
-		}
+	if (g_mkdir(servfilename, 0755) != 0 && errno != EEXIST) {
+		purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
+		return FALSE;
 	}
 
 	/*
 	 * Check ~./silc/clientkeys directory
 	 */
-	if ((g_stat(clientfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(clientfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					clientfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 clientfilename, g_strerror(errno));
-			return FALSE;
-		}
+	if (g_mkdir(clientfilename, 0755) != 0 && errno != EEXIST) {
+		purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
+		return FALSE;
 	}
 
 	/*
 	 * Check ~./silc/friends directory
 	 */
-	if ((g_stat(friendsfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(friendsfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					friendsfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 friendsfilename, g_strerror(errno));
-			return FALSE;
-		}
+	if (g_mkdir(friendsfilename, 0755) != 0 && errno != EEXIST) {
+		purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
+		return FALSE;
 	}
 
 	/*
diff --git a/libpurple/util.c b/libpurple/util.c
--- a/libpurple/util.c
+++ b/libpurple/util.c
@@ -2696,7 +2696,11 @@ purple_util_write_data_to_file_absolute(
 		g_free(filename_temp);
 		return FALSE;
 	}
-	/* Use stat to be absolutely sure. */
+#ifndef __COVERITY__
+	/* Use stat to be absolutely sure.
+	 * It causes TOCTOU coverity warning (against g_rename below),
+	 * but it's not a threat for us.
+	 */
 	if ((g_stat(filename_temp, &st) == -1) || (st.st_size != real_size))
 	{
 		purple_debug_error("util", "Error writing data to file %s: "
@@ -2706,6 +2710,7 @@ purple_util_write_data_to_file_absolute(
 		g_free(filename_temp);
 		return FALSE;
 	}
+#endif /* __COVERITY__ */
 
 	/* Rename to the REAL name */
 	if (g_rename(filename_temp, filename_full) == -1)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.