[dacp] Fix segfault from invalid queries

When parsing a DACP request (pattern: ^/ctrl-int/[[:digit:]]+/playqueue-edit$)
with a command parameter being "move" and an edit-params parameter lacking a
colon, strchr(param, ':') at httpd_dacp.c:2038 will return NULL, and safe_atoi32
is called with its first parameter str being 1. This will bypass the NULL check
at src/misc.c:650 and causes a segmentation fault at the call to strtol at line
657.

Closes #1933
This commit is contained in:
ejurgensen 2025-10-08 19:49:01 +02:00
parent b7e385ffe0
commit 5f526c7a7e

View File

@ -1894,6 +1894,7 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
const char *querymodifier; const char *querymodifier;
const char *sort; const char *sort;
const char *param; const char *param;
const char *ptr;
char modifiedquery[32]; char modifiedquery[32];
int mode; int mode;
int plid; int plid;
@ -1955,7 +1956,8 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
else else
{ {
// Modify the query: Take the id from the editquery and use it as a queuefilter playlist id // Modify the query: Take the id from the editquery and use it as a queuefilter playlist id
ret = safe_atoi32(strchr(editquery, ':') + 1, &plid); ptr = strchr(editquery, ':');
ret = ptr ? safe_atoi32(ptr + 1, &plid) : -1;
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid playlist id in request: %s\n", editquery); DPRINTF(E_LOG, L_DACP, "Invalid playlist id in request: %s\n", editquery);
@ -2029,38 +2031,44 @@ dacp_reply_playqueueedit_move(struct httpd_request *hreq)
struct player_status status; struct player_status status;
int ret; int ret;
const char *param; const char *param;
const char *ptr;
int src; int src;
int dst; int dst;
param = httpd_query_value_find(hreq->query, "edit-params"); param = httpd_query_value_find(hreq->query, "edit-params");
if (param) if (!param)
{ goto out;
ret = safe_atoi32(strchr(param, ':') + 1, &src);
if (ret < 0)
{
DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-from value in playqueue-edit request\n");
dacp_send_error(hreq, "cacr", "Invalid request"); ptr = strchr(param, ':');
return -1; if (!ptr)
} goto error;
ret = safe_atoi32(strchr(param, ',') + 1, &dst); ret = safe_atoi32(ptr + 1, &src);
if (ret < 0) if (ret < 0)
{ goto error;
DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-to value in playqueue-edit request\n");
dacp_send_error(hreq, "cacr", "Invalid request"); ptr = strchr(param, ',');
return -1; if (!ptr)
} goto error;
player_get_status(&status); ret = safe_atoi32(ptr + 1, &dst);
db_queue_move_byposrelativetoitem(src, dst, status.item_id, status.shuffle); if (ret < 0)
} goto error;
player_get_status(&status);
db_queue_move_byposrelativetoitem(src, dst, status.item_id, status.shuffle);
out:
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", HTTPD_SEND_NO_GZIP);
return 0; return 0;
error:
DPRINTF(E_LOG, L_DACP, "Invalid edit-params in playqueue-edit request: '%s'\n", param);
dacp_send_error(hreq, "cacr", "Invalid request");
return -1;
} }
static int static int
@ -2538,8 +2546,7 @@ dacp_reply_setspeakers(struct httpd_request *hreq)
} }
nspk = 1; nspk = 1;
ptr = param; for (ptr = param; ptr; ptr = strchr(ptr + 1, ','))
while ((ptr = strchr(ptr + 1, ',')))
nspk++; nspk++;
CHECK_NULL(L_DACP, ids = calloc((nspk + 1), sizeof(uint64_t))); CHECK_NULL(L_DACP, ids = calloc((nspk + 1), sizeof(uint64_t)));