[svn-commits] rmudgett: branch 1.8 r351618 - in /branches/1.8/channels: ./ sip/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Jan 19 17:17:35 CST 2012
Author: rmudgett
Date: Thu Jan 19 17:17:31 2012
New Revision: 351618
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=351618
Log:
Misc minor fixes in reqresp_parser.c and chan_sip.c.
* Fix corner cases in get_calleridname() parsing and ensure that the
output buffer is nul terminated.
* Make get_calleridname() truncate the name it parses if the given buffer
is too small rather than abandoning the parse and not returning anything
for the name. Adjusted get_calleridname_test() unit test to handle the
truncation change.
* Fix get_in_brackets_test() unit test to check the results of
get_in_brackets() correctly.
* Fix parse_name_andor_addr() to not return the address of a local buffer.
This function is currently not used.
* Fix potential NULL pointer dereference in sip_sendtext().
* No need to memset(calleridname) in check_user_full() or tmp_name in
get_name_and_number() because get_calleridname() ensures that it is nul
terminated.
* Reply with an accurate response if get_msg_text() fails in
receive_message(). This is academic in v1.8 because get_msg_text() can
never fail.
Modified:
branches/1.8/channels/chan_sip.c
branches/1.8/channels/sip/reqresp_parser.c
Modified: branches/1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/chan_sip.c?view=diff&rev=351618&r1=351617&r2=351618
==============================================================================
--- branches/1.8/channels/chan_sip.c (original)
+++ branches/1.8/channels/chan_sip.c Thu Jan 19 17:17:31 2012
@@ -4450,20 +4450,26 @@
static int sip_sendtext(struct ast_channel *ast, const char *text)
{
struct sip_pvt *dialog = ast->tech_pvt;
- int debug = sip_debug_test_pvt(dialog);
-
- if (!dialog)
+ int debug;
+
+ if (!dialog) {
return -1;
+ }
/* NOT ast_strlen_zero, because a zero-length message is specifically
* allowed by RFC 3428 (See section 10, Examples) */
- if (!text)
+ if (!text) {
return 0;
+ }
if(!is_method_allowed(&dialog->allowed_methods, SIP_MESSAGE)) {
ast_debug(2, "Trying to send MESSAGE to device that does not support it.\n");
return(0);
}
- if (debug)
+
+ debug = sip_debug_test_pvt(dialog);
+ if (debug) {
ast_verbose("Sending text %s on %s\n", text, ast->name);
+ }
+
transmit_message_with_text(dialog, text);
return 0;
}
@@ -15953,7 +15959,6 @@
ast_copy_string(from, get_header(req, "From"), sizeof(from));
/* XXX here tries to map the username for invite things */
- memset(calleridname, 0, sizeof(calleridname));
/* strip the display-name portion off the beginning of the FROM header. */
if (!(of = (char *) get_calleridname(from, calleridname, sizeof(calleridname)))) {
@@ -16127,9 +16132,10 @@
if (get_msg_text(buf, sizeof(buf), req)) {
ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
- transmit_response(p, "202 Accepted", req);
- if (!p->owner)
+ transmit_response(p, "500 Internal Server Error", req);
+ if (!p->owner) {
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ }
return;
}
Modified: branches/1.8/channels/sip/reqresp_parser.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/sip/reqresp_parser.c?view=diff&rev=351618&r1=351617&r2=351618
==============================================================================
--- branches/1.8/channels/sip/reqresp_parser.c (original)
+++ branches/1.8/channels/sip/reqresp_parser.c Thu Jan 19 17:17:31 2012
@@ -685,63 +685,77 @@
char *orig_output = output;
const char *orig_input = input;
+ if (!output || !outputsize) {
+ /* Bad output parameters. Should never happen. */
+ return input;
+ }
+
/* clear any empty characters in the beginning */
input = ast_skip_blanks(input);
- /* no data at all or no storage room? */
- if (!input || *input == '<' || !outputsize || !output) {
- return orig_input;
- }
-
/* make sure the output buffer is initilized */
*orig_output = '\0';
/* make room for '\0' at the end of the output buffer */
- outputsize--;
+ --outputsize;
+
+ /* no data at all or no display name? */
+ if (!input || *input == '<') {
+ return input;
+ }
/* quoted-string rules */
if (input[0] == '"') {
input++; /* skip the first " */
- for (;((outputsize > 0) && *input); input++) {
+ for (; *input; ++input) {
if (*input == '"') { /* end of quoted-string */
break;
} else if (*input == 0x5c) { /* quoted-pair = "\" (%x00-09 / %x0B-0C / %x0E-7F) */
- input++;
- if (!*input || (unsigned char)*input > 0x7f || *input == 0xa || *input == 0xd) {
+ ++input;
+ if (!*input) {
+ break;
+ }
+ if ((unsigned char) *input > 0x7f || *input == 0xa || *input == 0xd) {
continue; /* not a valid quoted-pair, so skip it */
}
- } else if (((*input != 0x9) && ((unsigned char) *input < 0x20)) ||
- (*input == 0x7f)) {
+ } else if ((*input != 0x9 && (unsigned char) *input < 0x20)
+ || *input == 0x7f) {
continue; /* skip this invalid character. */
}
- *output++ = *input;
- outputsize--;
+ if (0 < outputsize) {
+ /* We still have room for the output display-name. */
+ *output++ = *input;
+ --outputsize;
+ }
}
/* if this is successful, input should be at the ending quote */
- if (!input || *input != '"') {
+ if (*input != '"') {
ast_log(LOG_WARNING, "No ending quote for display-name was found\n");
*orig_output = '\0';
return orig_input;
}
/* make sure input is past the last quote */
- input++;
-
- /* terminate outbuf */
+ ++input;
+
+ /* terminate output */
*output = '\0';
} else { /* either an addr-spec or tokenLWS-combo */
- for (;((outputsize > 0) && *input); input++) {
+ for (; *input; ++input) {
/* token or WSP (without LWS) */
if ((*input >= '0' && *input <= '9') || (*input >= 'A' && *input <= 'Z')
|| (*input >= 'a' && *input <= 'z') || *input == '-' || *input == '.'
|| *input == '!' || *input == '%' || *input == '*' || *input == '_'
|| *input == '+' || *input == '`' || *input == '\'' || *input == '~'
|| *input == 0x9 || *input == ' ') {
- *output++ = *input;
- outputsize -= 1;
+ if (0 < outputsize) {
+ /* We still have room for the output display-name. */
+ *output++ = *input;
+ --outputsize;
+ }
} else if (*input == '<') { /* end of tokenLWS-combo */
/* we could assert that the previous char is LWS, but we don't care */
break;
@@ -759,10 +773,10 @@
return orig_input;
}
- /* set NULL while trimming trailing whitespace */
+ /* terminate output while trimming any trailing whitespace */
do {
*output-- = '\0';
- } while (*output == 0x9 || *output == ' '); /* we won't go past orig_output as first was a non-space */
+ } while (orig_output <= output && (*output == 0x9 || *output == ' '));
}
return input;
@@ -771,11 +785,12 @@
AST_TEST_DEFINE(get_calleridname_test)
{
int res = AST_TEST_PASS;
- const char *in1 = "\" quoted-text internal \\\" quote \"<stuff>";
+ const char *in1 = " \" quoted-text internal \\\" quote \"<stuff>";
const char *in2 = " token text with no quotes <stuff>";
const char *overflow1 = " \"quoted-text overflow 1234567890123456789012345678901234567890\" <stuff>";
+ const char *overflow2 = " non-quoted text overflow 1234567890123456789012345678901234567890 <stuff>";
const char *noendquote = " \"quoted-text no end <stuff>";
- const char *addrspec = " \"sip:blah at blah <stuff>";
+ const char *addrspec = " sip:blah at blah";
const char *no_quotes_no_brackets = "blah at blah";
const char *after_dname;
char dname[40];
@@ -810,8 +825,16 @@
/* quoted-text buffer overflow */
after_dname = get_calleridname(overflow1, dname, sizeof(dname));
ast_test_status_update(test, "overflow display-name1: %s\nafter: %s\n", dname, after_dname);
- if (*dname != '\0' && after_dname != overflow1) {
+ if (strcmp(dname, "quoted-text overflow 123456789012345678")) {
ast_test_status_update(test, "overflow display-name1 test failed\n");
+ res = AST_TEST_FAIL;
+ }
+
+ /* non-quoted-text buffer overflow */
+ after_dname = get_calleridname(overflow2, dname, sizeof(dname));
+ ast_test_status_update(test, "overflow display-name2: %s\nafter: %s\n", dname, after_dname);
+ if (strcmp(dname, "non-quoted text overflow 12345678901234")) {
+ ast_test_status_update(test, "overflow display-name2 test failed\n");
res = AST_TEST_FAIL;
}
@@ -825,7 +848,7 @@
/* addr-spec rather than display-name. */
after_dname = get_calleridname(addrspec, dname, sizeof(dname));
- ast_test_status_update(test, "noendquote display-name1: %s\nafter: %s\n", dname, after_dname);
+ ast_test_status_update(test, "addr-spec display-name1: %s\nafter: %s\n", dname, after_dname);
if (*dname != '\0' && after_dname != addrspec) {
ast_test_status_update(test, "detection of addr-spec failed\n");
res = AST_TEST_FAIL;
@@ -839,14 +862,13 @@
res = AST_TEST_FAIL;
}
-
return res;
}
int get_name_and_number(const char *hdr, char **name, char **number)
{
char header[256];
- char tmp_name[50] = { 0, };
+ char tmp_name[50];
char *tmp_number = NULL;
char *hostport = NULL;
char *dummy = NULL;
@@ -1069,14 +1091,14 @@
AST_TEST_DEFINE(get_in_brackets_test)
{
int res = AST_TEST_PASS;
- char *in_brackets = "<sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
+ char in_brackets[] = "sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah";
char no_name[] = "<sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
char quoted_string[] = "\"I'm a quote stri><ng\" <sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
char missing_end_quote[] = "\"I'm a quote string <sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
char name_no_quotes[] = "name not in quotes <sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
char no_end_bracket[] = "name not in quotes <sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah";
char no_name_no_brackets[] = "sip:name at host";
- char missing_start_bracket[] = "name not in quotes sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
+ char missing_start_bracket[] = "sip:name:secret at host:port;transport=tcp?headers=testblah&headers2=blahblah>";
char *uri = NULL;
switch (cmd) {
@@ -1093,57 +1115,49 @@
}
/* Test 1, simple get in brackets */
- if (!(uri = get_in_brackets(no_name)) || !(strcmp(uri, in_brackets))) {
-
- ast_test_status_update(test, "Test 1, simple get in brackets failed.\n");
+ if (!(uri = get_in_brackets(no_name)) || strcmp(uri, in_brackets)) {
+ ast_test_status_update(test, "Test 1, simple get in brackets failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 2, starts with quoted string */
- if (!(uri = get_in_brackets(quoted_string)) || !(strcmp(uri, in_brackets))) {
-
- ast_test_status_update(test, "Test 2, get in brackets with quoted string in front failed.\n");
+ if (!(uri = get_in_brackets(quoted_string)) || strcmp(uri, in_brackets)) {
+ ast_test_status_update(test, "Test 2, get in brackets with quoted string in front failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 3, missing end quote */
- if (!(uri = get_in_brackets(missing_end_quote)) || !(strcmp(uri, in_brackets))) {
-
- ast_test_status_update(test, "Test 3, missing end quote failed.\n");
+ if (!(uri = get_in_brackets(missing_end_quote)) || !strcmp(uri, in_brackets)) {
+ ast_test_status_update(test, "Test 3, missing end quote failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 4, starts with a name not in quotes */
- if (!(uri = get_in_brackets(name_no_quotes)) || !(strcmp(uri, in_brackets))) {
-
- ast_test_status_update(test, "Test 4, passing name not in quotes failed.\n");
+ if (!(uri = get_in_brackets(name_no_quotes)) || strcmp(uri, in_brackets)) {
+ ast_test_status_update(test, "Test 4, passing name not in quotes failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 5, no end bracket, should just return everything after the first '<' */
- if (!(uri = get_in_brackets(no_end_bracket)) || !(strcmp(uri, in_brackets))) {
-
- ast_test_status_update(test, "Test 5, no end bracket failed.\n");
+ if (!(uri = get_in_brackets(no_end_bracket)) || !strcmp(uri, in_brackets)) {
+ ast_test_status_update(test, "Test 5, no end bracket failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 6, NULL input */
if ((uri = get_in_brackets(NULL))) {
-
ast_test_status_update(test, "Test 6, NULL input failed.\n");
res = AST_TEST_FAIL;
}
/* Test 7, no name, and no brackets. */
- if (!(uri = get_in_brackets(no_name_no_brackets)) || (strcmp(uri, "sip:name at host"))) {
-
+ if (!(uri = get_in_brackets(no_name_no_brackets)) || strcmp(uri, "sip:name at host")) {
ast_test_status_update(test, "Test 7 failed. %s\n", uri);
res = AST_TEST_FAIL;
}
/* Test 8, no start bracket, but with ending bracket. */
- if (!(uri = get_in_brackets(missing_start_bracket)) || !(strcmp(uri, in_brackets))) {
-
+ if (!(uri = get_in_brackets(missing_start_bracket)) || strcmp(uri, in_brackets)) {
ast_test_status_update(test, "Test 8 failed. %s\n", uri);
res = AST_TEST_FAIL;
}
@@ -1158,20 +1172,42 @@
char **residue)
{
char buf[1024];
- char **residue2=residue;
+ char **residue2 = residue;
+ char *orig_uri = uri;
int ret;
+
+ buf[0] = '\0';
if (name) {
- get_calleridname(uri,buf,sizeof(buf));
- *name = buf;
- }
- ret = get_in_brackets_full(uri,&uri,residue);
- if (ret == 0) { /* uri is in brackets so do not treat unknown trailing uri parameters as potential messageheader parameters */
- *residue = *residue + 1; /* step over the first semicolon so as per parse uri residue */
+ uri = (char *) get_calleridname(uri, buf, sizeof(buf));
+ }
+ ret = get_in_brackets_full(uri, &uri, residue);
+ if (ret == 0) {
+ /*
+ * The uri is in brackets so do not treat unknown trailing uri
+ * parameters as potential message header parameters.
+ */
+ if (residue && **residue) {
+ /* step over the first semicolon as per parse_uri_full residue */
+ *residue = *residue + 1;
+ }
residue2 = NULL;
}
- return parse_uri_full(uri, scheme, user, pass, hostport, params, headers,
- residue2);
+ if (name) {
+ if (buf[0]) {
+ /*
+ * There is always room at orig_uri for the display-name because
+ * at least one character has always been removed. A '"' or '<'
+ * has been removed.
+ */
+ strcpy(orig_uri, buf);
+ *name = orig_uri;
+ } else {
+ *name = "";
+ }
+ }
+
+ return parse_uri_full(uri, scheme, user, pass, hostport, params, headers, residue2);
}
AST_TEST_DEFINE(parse_name_andor_addr_test)
@@ -1313,7 +1349,7 @@
name = user = pass = hostport = headers = residue = NULL;
params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
params.lr = 0;
- ast_copy_string(uri,testdataptr->uri,sizeof(uri));
+ ast_copy_string(uri,testdataptr->uri,sizeof(uri));
if (parse_name_andor_addr(uri, "sip:,sips:",
testdataptr->nameptr,
testdataptr->userptr,
@@ -1330,17 +1366,17 @@
((testdataptr->residueptr) && strcmp(testdataptr->residue, residue)) ||
((testdataptr->paramsptr) && strcmp(testdataptr->params.transport,params.transport)) ||
((testdataptr->paramsptr) && strcmp(testdataptr->params.user,params.user))
- ) {
- ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
- res = AST_TEST_FAIL;
- }
- }
-
+ ) {
+ ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
+ res = AST_TEST_FAIL;
+ }
+ }
return res;
}
-int get_comma(char *in, char **out) {
+int get_comma(char *in, char **out)
+{
char *c;
char *parse = in;
if (out) {
@@ -1376,35 +1412,35 @@
return 1;
}
-int parse_contact_header(char *contactheader, struct contactliststruct *contactlist) {
+int parse_contact_header(char *contactheader, struct contactliststruct *contactlist)
+{
int res;
int last;
char *comma;
char *residue;
char *param;
char *value;
- struct contact *contact=NULL;
+ struct contact *split_contact = NULL;
if (*contactheader == '*') {
return 1;
}
- contact = malloc(sizeof(*contact));
-
- AST_LIST_HEAD_SET_NOLOCK(contactlist, contact);
- while ((last = get_comma(contactheader,&comma)) != -1) {
-
+ split_contact = ast_calloc(1, sizeof(*split_contact));
+
+ AST_LIST_HEAD_SET_NOLOCK(contactlist, split_contact);
+ while ((last = get_comma(contactheader, &comma)) != -1) {
res = parse_name_andor_addr(contactheader, "sip:,sips:",
- &contact->name, &contact->user,
- &contact->pass, &contact->hostport,
- &contact->params, &contact->headers,
- &residue);
+ &split_contact->name, &split_contact->user,
+ &split_contact->pass, &split_contact->hostport,
+ &split_contact->params, &split_contact->headers,
+ &residue);
if (res == -1) {
return res;
}
/* parse contact params */
- contact->expires = contact->q = "";
+ split_contact->expires = split_contact->q = "";
while ((value = strchr(residue,'='))) {
*value++ = '\0';
@@ -1417,20 +1453,19 @@
}
if (!strcmp(param,"expires")) {
- contact->expires = value;
+ split_contact->expires = value;
} else if (!strcmp(param,"q")) {
- contact->q = value;
+ split_contact->q = value;
}
}
- if(last) {
+ if (last) {
return 0;
}
contactheader = comma;
- contact = malloc(sizeof(*contact));
- AST_LIST_INSERT_TAIL(contactlist, contact, list);
-
+ split_contact = ast_calloc(1, sizeof(*split_contact));
+ AST_LIST_INSERT_TAIL(contactlist, split_contact, list);
}
return last;
}
@@ -1563,16 +1598,15 @@
strcmp(tdcontactptr->params.transport, contactptr->params.transport) ||
strcmp(tdcontactptr->params.ttl, contactptr->params.ttl) ||
(tdcontactptr->params.lr != contactptr->params.lr)
- ) {
+ ) {
ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
res = AST_TEST_FAIL;
break;
}
- contactptr = AST_LIST_NEXT(contactptr,list);
+ contactptr = AST_LIST_NEXT(contactptr,list);
}
}
-
}
return res;
More information about the svn-commits
mailing list