From 6c9f9c136b72b4453c39eca4edb70b48f53b8d2c Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Tue, 20 Aug 2019 20:31:36 +0200
Subject: [PATCH] command/all: don't create new Response instance in exception
 handler

The new Response instance in the `catch` block didn't have the
`command` attribute set, so the error response didn't indicate which
command had failed, which however is required in the MPD protocol.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/628
---
 NEWS                        |  2 ++
 src/command/AllCommands.cxx | 47 +++++++++++++++++++------------------
 2 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/NEWS b/NEWS
index d47a02aff..e1859419f 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ ver 0.21.14 (not yet released)
 * player
   - fix crash after song change
   - fix seek position after restarting the decoder
+* protocol
+  - include command name in error responses
 
 ver 0.21.13 (2019/08/06)
 * input
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx
index a9fac6919..7926b7128 100644
--- a/src/command/AllCommands.cxx
+++ b/src/command/AllCommands.cxx
@@ -363,7 +363,7 @@ command_checked_lookup(Response &r, unsigned permission,
 
 CommandResult
 command_process(Client &client, unsigned num, char *line) noexcept
-try {
+{
 	Response r(client, num);
 
 	/* get the command name (first word on the line) */
@@ -391,32 +391,33 @@ try {
 	char *argv[COMMAND_ARGV_MAX];
 	Request args(argv, 0);
 
-	/* now parse the arguments (quoted or unquoted) */
+	try {
+		/* now parse the arguments (quoted or unquoted) */
 
-	while (true) {
-		if (args.size == COMMAND_ARGV_MAX) {
-			r.Error(ACK_ERROR_ARG, "Too many arguments");
-			return CommandResult::ERROR;
+		while (true) {
+			if (args.size == COMMAND_ARGV_MAX) {
+				r.Error(ACK_ERROR_ARG, "Too many arguments");
+				return CommandResult::ERROR;
+			}
+
+			char *a = tokenizer.NextParam();
+			if (a == nullptr)
+				break;
+
+			argv[args.size++] = a;
 		}
 
-		char *a = tokenizer.NextParam();
-		if (a == nullptr)
-			break;
+		/* look up and invoke the command handler */
 
-		argv[args.size++] = a;
-	}
+		const struct command *cmd =
+			command_checked_lookup(r, client.GetPermission(),
+					       cmd_name, args);
+		if (cmd == nullptr)
+			return CommandResult::ERROR;
 
-	/* look up and invoke the command handler */
-
-	const struct command *cmd =
-		command_checked_lookup(r, client.GetPermission(),
-				       cmd_name, args);
-	if (cmd == nullptr)
+		return cmd->handler(client, args, r);
+	} catch (...) {
+		PrintError(r, std::current_exception());
 		return CommandResult::ERROR;
-
-	return cmd->handler(client, args, r);
-} catch (...) {
-	Response r(client, num);
-	PrintError(r, std::current_exception());
-	return CommandResult::ERROR;
+	}
 }