diff --git a/channels/chan_local.c b/channels/chan_local.c index a9a27ff8c2..936264d21e 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -203,23 +203,17 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_fra /* Recalculate outbound channel */ other = isoutbound ? p->owner : p->chan; - /* Set glare detection */ - ast_set_flag(p, LOCAL_GLARE_DETECT); - if (ast_test_flag(p, LOCAL_CANCEL_QUEUE)) { - /* We had a glare on the hangup. Forget all this business, - return and destroy p. */ - ast_mutex_unlock(&p->lock); - p = local_pvt_destroy(p); - return -1; - } if (!other) { - ast_clear_flag(p, LOCAL_GLARE_DETECT); return 0; } /* do not queue frame if generator is on both local channels */ - if (us && us->generator && other->generator) + if (us && us->generator && other->generator) { return 0; + } + + /* Set glare detection */ + ast_set_flag(p, LOCAL_GLARE_DETECT); /* Ensure that we have both channels locked */ while (other && ast_channel_trylock(other)) { @@ -235,6 +229,17 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_fra other = isoutbound ? p->owner : p->chan; } + /* Since glare detection only occurs within this function, and because + * a pvt flag cannot be set without having the pvt lock, this is the only + * location where we could detect a cancelling of the queue. */ + if (ast_test_flag(p, LOCAL_CANCEL_QUEUE)) { + /* We had a glare on the hangup. Forget all this business, + return and destroy p. */ + ast_mutex_unlock(&p->lock); + p = local_pvt_destroy(p); + return -1; + } + if (other) { ast_queue_frame(other, f); ast_channel_unlock(other); diff --git a/funcs/func_env.c b/funcs/func_env.c index 4eba211bb0..095252b5ae 100644 --- a/funcs/func_env.c +++ b/funcs/func_env.c @@ -113,40 +113,59 @@ static int file_read(struct ast_channel *chan, const char *cmd, char *data, char AST_APP_ARG(offset); AST_APP_ARG(length); ); - int offset = 0, length; + int offset = 0, length, res = 0; char *contents; + size_t contents_len; AST_STANDARD_APP_ARGS(args, data); - if (args.argc > 1) + if (args.argc > 1) { offset = atoi(args.offset); + } if (args.argc > 2) { - if ((length = atoi(args.length)) < 1) { - ast_log(LOG_WARNING, "Invalid length '%s'. Returning the max (%d)\n", args.length, (int)len); - length = len; - } else if (length > len) { - ast_log(LOG_WARNING, "Length %d is greater than the max (%d). Truncating output.\n", length, (int)len); + /* The +1/-1 in this code section is to accomodate for the terminating NULL. */ + if ((length = atoi(args.length) + 1) > len) { + ast_log(LOG_WARNING, "Length %d is greater than the max (%d). Truncating output.\n", length - 1, (int)len - 1); length = len; } - } else + } else { length = len; + } - if (!(contents = ast_read_textfile(args.filename))) + if (!(contents = ast_read_textfile(args.filename))) { return -1; + } - if (offset >= 0) - ast_copy_string(buf, &contents[offset], length); - else { - size_t tmp = strlen(contents); - if (offset * -1 > tmp) { - ast_log(LOG_WARNING, "Offset is larger than the file size.\n"); - offset = tmp * -1; + do { + contents_len = strlen(contents); + if (offset > contents_len) { + res = -1; + break; } - ast_copy_string(buf, &contents[tmp + offset], length); - } + + if (offset >= 0) { + if (length < 0) { + if (contents_len - offset + length < 0) { + /* Nothing left after trimming */ + res = -1; + break; + } + ast_copy_string(buf, &contents[offset], contents_len + length); + } else { + ast_copy_string(buf, &contents[offset], length); + } + } else { + if (offset * -1 > contents_len) { + ast_log(LOG_WARNING, "Offset is larger than the file size.\n"); + offset = contents_len * -1; + } + ast_copy_string(buf, &contents[contents_len + offset], length); + } + } while (0); + ast_free(contents); - return 0; + return res; } static struct ast_custom_function env_function = {