Fix crash in PresenceState AMI action when specifying an invalid provider
authorMatthew Jordan <mjordan@digium.com>
Fri, 15 Feb 2013 23:29:28 +0000 (23:29 +0000)
committerMatthew Jordan <mjordan@digium.com>
Fri, 15 Feb 2013 23:29:28 +0000 (23:29 +0000)
This patch fixes a crash in Asterisk that could be caused by using the
PresenceState AMI action while providing an invalid provider. This patch
also adds some additional warnings when a user attempts to provide the
PresenceState action with invalid data, and removes some NOTICE statements
that were still lurking in the code from testing.

(closes issue AST-1084)
Reported by: John Bigelow
Tested by: John Bigelow
........

Merged revisions 381594 from http://svn.asterisk.org/svn/asterisk/branches/11

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@381595 65c4cc65-6c06-0410-ace0-fbb531ad65f3

funcs/func_presencestate.c
main/manager.c
main/presencestate.c

index e62cf7d..51df750 100644 (file)
@@ -243,7 +243,7 @@ static enum ast_presence_state custom_presence_callback(const char *data, char *
        ast_db_get(astdb_family, data, buf, sizeof(buf));
 
        if (parse_data(buf, &state, &_subtype, &_message, &_options)) {
-               return -1;
+               return AST_PRESENCE_INVALID;
        }
 
        if ((strchr(_options, 'e'))) {
@@ -252,7 +252,6 @@ static enum ast_presence_state custom_presence_callback(const char *data, char *
                        *subtype = NULL;
                } else {
                        memset(tmp, 0, sizeof(tmp));
-                       ast_log(LOG_NOTICE, "Hey there, I'm doing some base64 decoding\n");
                        ast_base64decode((unsigned char *) tmp, _subtype, sizeof(tmp) - 1);
                        *subtype = ast_strdup(tmp);
                }
@@ -261,12 +260,10 @@ static enum ast_presence_state custom_presence_callback(const char *data, char *
                        *message = NULL;
                } else {
                        memset(tmp, 0, sizeof(tmp));
-                       ast_log(LOG_NOTICE, "Hey there, I'm doing some more base64 decoding\n");
                        ast_base64decode((unsigned char *) tmp, _message, sizeof(tmp) - 1);
                        *message = ast_strdup(tmp);
                }
        } else {
-               ast_log(LOG_NOTICE, "Not doing any base64 decoding\n");
                *subtype = ast_strlen_zero(_subtype) ? NULL : ast_strdup(_subtype);
                *message = ast_strlen_zero(_message) ? NULL : ast_strdup(_message);
        }
index 0543ee6..2c67517 100644 (file)
@@ -2280,6 +2280,7 @@ void astman_send_error_va(struct mansession *s, const struct message *m, const c
 {
        va_list ap;
        struct ast_str *buf;
+       char *msg;
 
        if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
                return;
@@ -2289,8 +2290,13 @@ void astman_send_error_va(struct mansession *s, const struct message *m, const c
        ast_str_set_va(&buf, 0, fmt, ap);
        va_end(ap);
 
-       astman_send_response_full(s, m, "Error", ast_str_buffer(buf), NULL);
-       ast_free(buf);
+       /* astman_append will use the same underlying buffer, so copy the message out
+        * before sending the response */
+       msg = ast_str_buffer(buf);
+       if (msg) {
+               msg = ast_strdupa(msg);
+       }
+       astman_send_response_full(s, m, "Error", msg, NULL);
 }
 
 void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
@@ -3378,7 +3384,7 @@ static int action_hangup(struct mansession *s, const struct message *m)
 
        /* if regex compilation fails, hangup fails */
        if (regcomp(&regexbuf, ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
-               astman_send_error_va(s, m, "Regex compile failed on: %s\n", name_or_regex);
+               astman_send_error_va(s, m, "Regex compile failed on: %s", name_or_regex);
                ast_free(regex_string);
                return 0;
        }
@@ -4610,6 +4616,10 @@ static int action_presencestate(struct mansession *s, const struct message *m)
        }
 
        state = ast_presence_state(provider, &subtype, &message);
+       if (state == AST_PRESENCE_INVALID) {
+               astman_send_error_va(s, m, "Invalid provider %s or provider in invalid state", provider);
+               return 0;
+       }
 
        if (!ast_strlen_zero(subtype)) {
                snprintf(subtype_header, sizeof(subtype_header),
index 94d0dc6..b87b092 100644 (file)
@@ -159,6 +159,9 @@ static enum ast_presence_state ast_presence_state_helper(const char *presence_pr
        }
        AST_RWLIST_UNLOCK(&presence_state_providers);
 
+       if (!provider) {
+               ast_log(LOG_WARNING, "No provider found for label %s\n", label);
+       }
 
        return res;
 }