changeset 19813:7e9b5db56a85

doveadm-http: Handle invalid input better for arrays.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 22 Feb 2016 19:56:35 +0200
parents 899c7a0345dd
children 79ca5c365eac
files src/doveadm/client-connection-http.c
diffstat 1 files changed, 26 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/client-connection-http.c	Sat Feb 20 23:16:52 2016 +0200
+++ b/src/doveadm/client-connection-http.c	Mon Feb 22 19:56:35 2016 +0200
@@ -54,6 +54,7 @@
 		JSON_STATE_COMMAND_PARAMETERS,
 		JSON_STATE_COMMAND_PARAMETER_KEY,
 		JSON_STATE_COMMAND_PARAMETER_VALUE,
+		JSON_STATE_COMMAND_PARAMETER_VALUE_ARRAY,
 		JSON_STATE_COMMAND_PARAMETER_VALUE_ISTREAM_CONSUME,
 		JSON_STATE_COMMAND_ID,
 		JSON_STATE_COMMAND_DONE,
@@ -204,6 +205,19 @@
 		if (rc != 1) return rc;
 		conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
 		return json_parse_next(conn->json_parser, type, value);
+	} else if (conn->json_state == JSON_STATE_COMMAND_PARAMETER_VALUE_ARRAY) {
+		/* reading through parameters in an array */
+		while ((rc = json_parse_next(conn->json_parser, type, value)) > 0) {
+			if (*type == JSON_TYPE_ARRAY_END) {
+				conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
+				return json_parse_next(conn->json_parser, type, value);
+			}
+			if (*type != JSON_TYPE_STRING)
+				return -2;
+			tmp = p_strdup(conn->client.pool,*value);
+			array_append(&conn->cmd_param->value.v_array, &tmp, 1);
+		}
+		return rc;
 	} else if (conn->json_state == JSON_STATE_COMMAND_PARAMETER_VALUE) {
 		if (conn->cmd_param->type == CMD_PARAM_ISTREAM) {
 			if (conn->cmd_param->value_set == TRUE)
@@ -219,43 +233,23 @@
 		}
 		rc = json_parse_next(conn->json_parser, type, value);
 		if (rc != 1) return rc;
-		if (*type == JSON_TYPE_ARRAY_END) {
-			conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
-			return json_parse_next(conn->json_parser, type, value);
-		}
-		/* allow array for cmd_param_array only, and only once */
-		if (*type == JSON_TYPE_ARRAY && conn->cmd_param->type != CMD_PARAM_ARRAY)
-			return -2;
-		if (*type == JSON_TYPE_ARRAY) { /* start of array */
-			conn->value_is_array = TRUE;
-			rc = json_parse_next(conn->json_parser, type, value);
-			if (rc != 1) return rc;
-		}
 		if (conn->cmd_param->type == CMD_PARAM_ARRAY) {
+			p_array_init(&conn->cmd_param->value.v_array, conn->client.pool, 1);
+			conn->cmd_param->value_set = TRUE;
+			if (*type == JSON_TYPE_ARRAY) {
+				/* start of array */
+				conn->value_is_array = TRUE;
+				conn->json_state = JSON_STATE_COMMAND_PARAMETER_VALUE_ARRAY;
+				return doveadm_http_server_json_parse_next(conn, type, value);
+			}
 			if (*type != JSON_TYPE_STRING) {
 				/* FIXME: should handle other than string too */
 				return -2;
 			}
-			conn->cmd_param->value_set = TRUE;
-			if (!array_is_created(&conn->cmd_param->value.v_array))
-				p_array_init(&conn->cmd_param->value.v_array,conn->client.pool,1);
-			if (conn->value_is_array) {
-				while(rc == 1) {
-					tmp = p_strdup(conn->client.pool,*value);
-					array_append(&conn->cmd_param->value.v_array, &tmp, 1);
-					rc = json_parse_next(conn->json_parser, type, value);
-					if (*type == JSON_TYPE_ARRAY_END) {
-						conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
-						return json_parse_next(conn->json_parser, type, value);
-					}
-				}
-			} else {
-				tmp = p_strdup(conn->client.pool,*value);
-				array_append(&conn->cmd_param->value.v_array, &tmp, 1);
-				conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
-				return json_parse_next(conn->json_parser, type, value);
-			}
-			return rc;
+			tmp = p_strdup(conn->client.pool,*value);
+			array_append(&conn->cmd_param->value.v_array, &tmp, 1);
+			conn->json_state = JSON_STATE_COMMAND_PARAMETER_KEY;
+			return json_parse_next(conn->json_parser, type, value);
 		} else {
 			conn->cmd_param->value_set = TRUE;
 			switch(conn->cmd_param->type) {