mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-09 03:18:30 +00:00
Merge r429273 for AST-2014-019
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/13.1.0-rc2@429317 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
22
ChangeLog
22
ChangeLog
@@ -1,3 +1,25 @@
|
|||||||
|
2014-12-10 Asterisk Development Team <asteriskteam@digium.com>
|
||||||
|
|
||||||
|
* Asterisk 13.1.0-rc2 Released.
|
||||||
|
|
||||||
|
* AST-2014-019: Fix crash when receiving a WebSocket packet with a
|
||||||
|
payload length of zero.
|
||||||
|
|
||||||
|
Frames with a payload length of 0 were incorrectly handled in
|
||||||
|
res_http_websocket. Provided a frame with a payload had been
|
||||||
|
received prior it was possible for a double free to occur. The
|
||||||
|
realloc operation would succeed (thus freeing the payload) but be
|
||||||
|
treated as an error. When the session was then torn down the payload
|
||||||
|
would be freed again causing a crash. The read function now takes
|
||||||
|
this into account.
|
||||||
|
|
||||||
|
This change also fixes assumptions made by users of
|
||||||
|
res_http_websocket. There is no guarantee that a frame received from
|
||||||
|
it will be NULL terminated.
|
||||||
|
|
||||||
|
ASTERISK-24472 #close
|
||||||
|
Reported by: Badalian Vyacheslav
|
||||||
|
|
||||||
2014-12-08 Asterisk Development Team <asteriskteam@digium.com>
|
2014-12-08 Asterisk Development Team <asteriskteam@digium.com>
|
||||||
|
|
||||||
* Asterisk 13.1.0-rc1 Released.
|
* Asterisk 13.1.0-rc1 Released.
|
||||||
|
|||||||
@@ -2644,12 +2644,16 @@ static void sip_websocket_callback(struct ast_websocket *session, struct ast_var
|
|||||||
|
|
||||||
if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {
|
if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {
|
||||||
struct sip_request req = { 0, };
|
struct sip_request req = { 0, };
|
||||||
|
char data[payload_len + 1];
|
||||||
|
|
||||||
if (!(req.data = ast_str_create(payload_len + 1))) {
|
if (!(req.data = ast_str_create(payload_len + 1))) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast_str_set(&req.data, -1, "%s", payload) == AST_DYNSTR_BUILD_FAILED) {
|
strncpy(data, payload, payload_len);
|
||||||
|
data[payload_len] = '\0';
|
||||||
|
|
||||||
|
if (ast_str_set(&req.data, -1, "%s", data) == AST_DYNSTR_BUILD_FAILED) {
|
||||||
deinit_req(&req);
|
deinit_req(&req);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -513,14 +513,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
|
|
||||||
ast_log(LOG_WARNING, "Failed allocation: %p, %zu, %"PRIu64"\n",
|
|
||||||
session->payload, session->payload_len, *payload_len);
|
|
||||||
*payload_len = 0;
|
|
||||||
ast_websocket_close(session, 1009);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Per the RFC for PING we need to send back an opcode with the application data as received */
|
/* Per the RFC for PING we need to send back an opcode with the application data as received */
|
||||||
if ((*opcode == AST_WEBSOCKET_OPCODE_PING) && (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len))) {
|
if ((*opcode == AST_WEBSOCKET_OPCODE_PING) && (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len))) {
|
||||||
*payload_len = 0;
|
*payload_len = 0;
|
||||||
@@ -528,9 +520,22 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->payload = new_payload;
|
if (*payload_len) {
|
||||||
memcpy((session->payload + session->payload_len), (*payload), (*payload_len));
|
if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
|
||||||
session->payload_len += *payload_len;
|
ast_log(LOG_WARNING, "Failed allocation: %p, %zu, %"PRIu64"\n",
|
||||||
|
session->payload, session->payload_len, *payload_len);
|
||||||
|
*payload_len = 0;
|
||||||
|
ast_websocket_close(session, 1009);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->payload = new_payload;
|
||||||
|
memcpy((session->payload + session->payload_len), (*payload), (*payload_len));
|
||||||
|
session->payload_len += *payload_len;
|
||||||
|
} else if (!session->payload_len && session->payload) {
|
||||||
|
ast_free(session->payload);
|
||||||
|
session->payload = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) {
|
if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) {
|
||||||
/* If this is not a final message we need to defer returning it until later */
|
/* If this is not a final message we need to defer returning it until later */
|
||||||
|
|||||||
@@ -200,7 +200,8 @@ static int transport_read(void *data)
|
|||||||
|
|
||||||
pj_gettimeofday(&rdata->pkt_info.timestamp);
|
pj_gettimeofday(&rdata->pkt_info.timestamp);
|
||||||
|
|
||||||
pj_memcpy(rdata->pkt_info.packet, read_data->payload, sizeof(rdata->pkt_info.packet));
|
pj_memcpy(rdata->pkt_info.packet, read_data->payload,
|
||||||
|
PJSIP_MAX_PKT_LEN < read_data->payload_len ? PJSIP_MAX_PKT_LEN : read_data->payload_len);
|
||||||
rdata->pkt_info.len = read_data->payload_len;
|
rdata->pkt_info.len = read_data->payload_len;
|
||||||
rdata->pkt_info.zero = 0;
|
rdata->pkt_info.zero = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user