diff options
-rw-r--r-- | main/rtp_engine.c | 15 | ||||
-rw-r--r-- | res/res_pjsip.c | 59 | ||||
-rw-r--r-- | res/res_pjsip/presence_xml.c | 31 | ||||
-rw-r--r-- | res/res_pjsip_pidf_digium_body_supplement.c | 2 | ||||
-rw-r--r-- | res/res_pjsip_sdp_rtp.c | 24 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 9 |
6 files changed, 109 insertions, 31 deletions
diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 296d84f2c..c46370de4 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -603,6 +603,7 @@ void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs) void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance) { ast_rtp_codecs_payloads_destroy(codecs); + ast_rtp_codecs_payloads_initialize(codecs); if (instance && instance->engine && instance->engine->payload_set) { int i; @@ -610,8 +611,6 @@ void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp instance->engine->payload_set(instance, i, 0, NULL, 0); } } - - ast_rtp_codecs_payloads_initialize(codecs); } void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance) @@ -1716,12 +1715,16 @@ static void rtp_engine_mime_type_cleanup(int i) static void set_next_mime_type(struct ast_format *format, int rtp_code, const char *type, const char *subtype, unsigned int sample_rate) { - int x = mime_types_len; - if (ARRAY_LEN(ast_rtp_mime_types) == mime_types_len) { + int x; + + ast_rwlock_wrlock(&mime_types_lock); + + x = mime_types_len; + if (ARRAY_LEN(ast_rtp_mime_types) <= x) { + ast_rwlock_unlock(&mime_types_lock); return; } - ast_rwlock_wrlock(&mime_types_lock); /* Make sure any previous value in ast_rtp_mime_types is cleaned up */ memset(&ast_rtp_mime_types[x], 0, sizeof(struct ast_rtp_mime_type)); if (format) { @@ -1734,6 +1737,7 @@ static void set_next_mime_type(struct ast_format *format, int rtp_code, const ch ast_copy_string(ast_rtp_mime_types[x].subtype, subtype, sizeof(ast_rtp_mime_types[x].subtype)); ast_rtp_mime_types[x].sample_rate = sample_rate; mime_types_len++; + ast_rwlock_unlock(&mime_types_lock); } @@ -2095,6 +2099,7 @@ static void rtp_engine_shutdown(void) rtp_engine_mime_type_cleanup(x); } } + mime_types_len = 0; ast_rwlock_unlock(&mime_types_lock); } diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 43e3da6de..405ac6838 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -40,6 +40,8 @@ #include "asterisk/file.h" #include "asterisk/cli.h" #include "asterisk/res_pjsip_cli.h" +#include "asterisk/test.h" +#include "asterisk/res_pjsip_presence_xml.h" /*** MODULEINFO <depend>pjproject</depend> @@ -3701,6 +3703,57 @@ static void remove_request_headers(pjsip_endpoint *endpt) } } +AST_TEST_DEFINE(xml_sanitization_end_null) +{ + char sanitized[8]; + + switch (cmd) { + case TEST_INIT: + info->name = "xml_sanitization_end_null"; + info->category = "/res/res_pjsip/"; + info->summary = "Ensure XML sanitization works as expected with a long string"; + info->description = "This test sanitizes a string which exceeds the output\n" + "buffer size. Once done the string is confirmed to be NULL terminated."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + ast_sip_sanitize_xml("aaaaaaaaaaaa", sanitized, sizeof(sanitized)); + if (sanitized[7] != '\0') { + ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(xml_sanitization_exceeds_buffer) +{ + char sanitized[8]; + + switch (cmd) { + case TEST_INIT: + info->name = "xml_sanitization_exceeds_buffer"; + info->category = "/res/res_pjsip/"; + info->summary = "Ensure XML sanitization does not exceed buffer when output won't fit"; + info->description = "This test sanitizes a string which before sanitization would\n" + "fit within the output buffer. After sanitization, however, the string would\n" + "exceed the buffer. Once done the string is confirmed to be NULL terminated."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + ast_sip_sanitize_xml("<><><>&", sanitized, sizeof(sanitized)); + if (sanitized[7] != '\0') { + ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + /*! * \internal * \brief Reload configuration within a PJSIP thread @@ -3870,6 +3923,9 @@ static int load_module(void) ast_res_pjsip_init_options_handling(0); ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); + AST_TEST_REGISTER(xml_sanitization_end_null); + AST_TEST_REGISTER(xml_sanitization_exceeds_buffer); + return AST_MODULE_LOAD_SUCCESS; } @@ -3912,6 +3968,9 @@ static int unload_pjsip(void *data) static int unload_module(void) { + AST_TEST_UNREGISTER(xml_sanitization_end_null); + AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer); + /* The thread this is called from cannot call PJSIP/PJLIB functions, * so we have to push the work to the threadpool to handle */ diff --git a/res/res_pjsip/presence_xml.c b/res/res_pjsip/presence_xml.c index 12bfa078c..b98ea0237 100644 --- a/res/res_pjsip/presence_xml.c +++ b/res/res_pjsip/presence_xml.c @@ -30,45 +30,54 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len) { char *copy = ast_strdupa(input); char *break_point; + size_t remaining = len - 1; output[0] = '\0'; - while ((break_point = strpbrk(copy, "<>\"&'\n\r"))) { + while ((break_point = strpbrk(copy, "<>\"&'\n\r")) && remaining) { char to_escape = *break_point; *break_point = '\0'; - strncat(output, copy, len); + strncat(output, copy, remaining); + + /* The strncat function will write remaining+1 if the string length is + * equal to or greater than the size provided to it. We take this into + * account by subtracting 1, which ensures that the NULL byte is written + * inside of the provided buffer. + */ + remaining = len - strlen(output) - 1; switch (to_escape) { case '<': - strncat(output, "<", len); + strncat(output, "<", remaining); break; case '>': - strncat(output, ">", len); + strncat(output, ">", remaining); break; case '"': - strncat(output, """, len); + strncat(output, """, remaining); break; case '&': - strncat(output, "&", len); + strncat(output, "&", remaining); break; case '\'': - strncat(output, "'", len); + strncat(output, "'", remaining); break; case '\r': - strncat(output, " ", len); + strncat(output, " ", remaining); break; case '\n': - strncat(output, " ", len); + strncat(output, " ", remaining); break; }; copy = break_point + 1; + remaining = len - strlen(output) - 1; } /* Be sure to copy everything after the final bracket */ - if (*copy) { - strncat(output, copy, len); + if (*copy && remaining) { + strncat(output, copy, remaining); } } diff --git a/res/res_pjsip_pidf_digium_body_supplement.c b/res/res_pjsip_pidf_digium_body_supplement.c index 86e673afa..4b1a78181 100644 --- a/res/res_pjsip_pidf_digium_body_supplement.c +++ b/res/res_pjsip_pidf_digium_body_supplement.c @@ -40,7 +40,7 @@ static int pidf_supplement_body(void *body, void *data) { struct ast_sip_exten_state_data *state_data = data; pj_xml_node *node; - char sanitized[256]; + char sanitized[1024]; if (ast_strlen_zero(state_data->user_agent) || !strstr(state_data->user_agent, "digium")) { diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 4fcc6710b..d8605258f 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -237,13 +237,13 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp } ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name)); - if (strcmp(name,"telephone-event") == 0) { - tel_event++; - } + if (strcmp(name, "telephone-event") == 0) { + tel_event++; + } ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media)); - ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, pj_strtoul(&stream->desc.fmt[i]), - media, name, options, rtpmap->clock_rate); + ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, + pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate); /* Look for an optional associated fmtp attribute */ if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) { continue; @@ -270,8 +270,8 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp } } } - if ((tel_event==0) && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) { - ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND); + if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) { + ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND); } /* Get the packetization, if it exists */ if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) { @@ -329,7 +329,7 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi } ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp), - session_media->rtp); + session_media->rtp); ast_format_cap_append_from_cap(session->req_caps, joint, AST_MEDIA_TYPE_UNKNOWN); @@ -1137,8 +1137,12 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as /* Add non-codec formats */ if (media_type != AST_MEDIA_TYPE_VIDEO) { for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) { - if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), - 0, NULL, index)) == -1) { + if (!(noncodec & index)) { + continue; + } + rtp_code = ast_rtp_codecs_payload_code( + ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index); + if (rtp_code == -1) { continue; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 462091778..43615d6c8 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -4517,6 +4517,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc } payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype); + if (!payload) { + /* Unknown payload type. */ + return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; + } /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */ if (!payload->asterisk_format) { @@ -4543,10 +4547,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc /* Even if no frame was returned by one of the above methods, * we may have a frame to return in our frame list */ - if (!AST_LIST_EMPTY(&frames)) { - return AST_LIST_FIRST(&frames); - } - return &ast_null_frame; + return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; } ao2_replace(rtp->lastrxformat, payload->format); |