summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/rtp_engine.c15
-rw-r--r--res/res_pjsip.c59
-rw-r--r--res/res_pjsip/presence_xml.c31
-rw-r--r--res/res_pjsip_pidf_digium_body_supplement.c2
-rw-r--r--res/res_pjsip_sdp_rtp.c24
-rw-r--r--res/res_rtp_asterisk.c9
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, "&lt;", len);
+ strncat(output, "&lt;", remaining);
break;
case '>':
- strncat(output, "&gt;", len);
+ strncat(output, "&gt;", remaining);
break;
case '"':
- strncat(output, "&quot;", len);
+ strncat(output, "&quot;", remaining);
break;
case '&':
- strncat(output, "&amp;", len);
+ strncat(output, "&amp;", remaining);
break;
case '\'':
- strncat(output, "&apos;", len);
+ strncat(output, "&apos;", remaining);
break;
case '\r':
- strncat(output, "&#13;", len);
+ strncat(output, "&#13;", remaining);
break;
case '\n':
- strncat(output, "&#10;", len);
+ strncat(output, "&#10;", 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);