From 27535a7f781d7fbc87b2c6f9ec217cf7daca3323 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Mon, 3 Sep 2012 22:41:04 +0200
Subject: [PATCH] update_walk: fix unsafe readlink() usage

---
 NEWS              |  1 +
 src/update_walk.c | 12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index c23739d7a..22f42b775 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ ver 0.17.2 (2012/??/??)
 * playlist: fix memory leak
 * state_file: save song priorities
 * player: disable cross-fading in "single" mode
+* update: fix unsafe readlink() usage
 
 
 ver 0.17.1 (2012/07/31)
diff --git a/src/update_walk.c b/src/update_walk.c
index 615bf41a8..8554e8f3c 100644
--- a/src/update_walk.c
+++ b/src/update_walk.c
@@ -283,12 +283,20 @@ skip_symlink(const struct directory *directory, const char *utf8_name)
 		return true;
 
 	char buffer[MPD_PATH_MAX];
-	ssize_t ret = readlink(path_fs, buffer, sizeof(buffer));
+	ssize_t length = readlink(path_fs, buffer, sizeof(buffer));
 	g_free(path_fs);
-	if (ret < 0)
+	if (length < 0)
 		/* don't skip if this is not a symlink */
 		return errno != EINVAL;
 
+	if ((size_t)length >= sizeof(buffer))
+		/* skip symlinks when the buffer is too small for the
+		   link target */
+		return true;
+
+	/* null-terminate the buffer, because readlink() will not */
+	buffer[length] = 0;
+
 	if (!follow_inside_symlinks && !follow_outside_symlinks) {
 		/* ignore all symlinks */
 		return true;