summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
75b8515)
With dynamic chunks, afh_get_chunk() may fail. Currently
vss_get_chunk() prints an error message in this case and returns
the null pointer. However, some callers of vss_get_chunk() happily
dereference the returned pointer without checking for NULL.
This patch modifies vss_get_chunk() to return int and teaches all
callers to check the return value. For the udp and dccp transport,
we disable the fec client temporarily in the error case while for
the http transport we log the error (but otherwise ignore it), and
try to continue with the next chunk.
This flaw was noticed by the clang static analyzer.
-static void vss_get_chunk(int chunk_num, struct vss_task *vsst,
+static int vss_get_chunk(int chunk_num, struct vss_task *vsst,
char **buf, size_t *sz)
{
int ret;
char **buf, size_t *sz)
{
int ret;
assert(vsst->header_buf);
*buf = vsst->header_buf; /* stripped header */
*sz = vsst->header_len;
assert(vsst->header_buf);
*buf = vsst->header_buf; /* stripped header */
*sz = vsst->header_len;
}
ret = afh_get_chunk(chunk_num, &mmd->afd.afhi,
mmd->afd.audio_format_id, vsst->map, vsst->mapsize,
(const char **)buf, sz, &vsst->afh_context);
if (ret < 0) {
}
ret = afh_get_chunk(chunk_num, &mmd->afd.afhi,
mmd->afd.audio_format_id, vsst->map, vsst->mapsize,
(const char **)buf, sz, &vsst->afh_context);
if (ret < 0) {
- PARA_WARNING_LOG("could not get chunk %d: %s\n",
- chunk_num, para_strerror(-ret));
-static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
+static int compute_group_size(struct vss_task *vsst, struct fec_group *g,
int max_bytes)
{
char *buf;
size_t len;
int max_bytes)
{
char *buf;
size_t len;
- int i, max_chunks = PARA_MAX(1LU, 150 / tv2ms(vss_chunk_time()));
+ int ret, i, max_chunks = PARA_MAX(1LU, 150 / tv2ms(vss_chunk_time()));
if (g->first_chunk == 0) {
g->num_chunks = 1;
if (g->first_chunk == 0) {
g->num_chunks = 1;
- vss_get_chunk(0, vsst, &buf, &len);
+ ret = vss_get_chunk(0, vsst, &buf, &len);
+ if (ret < 0)
+ return ret;
break;
if (chunk_num >= mmd->afd.afhi.chunks_total) /* eof */
break;
break;
if (chunk_num >= mmd->afd.afhi.chunks_total) /* eof */
break;
- vss_get_chunk(chunk_num, vsst, &buf, &len);
+ ret = vss_get_chunk(chunk_num, vsst, &buf, &len);
+ if (ret < 0)
+ return ret;
if (g->bytes + len > max_bytes)
break;
/* Include this chunk */
if (g->bytes + len > max_bytes)
break;
/* Include this chunk */
g->num_chunks++;
}
assert(g->num_chunks);
g->num_chunks++;
}
assert(g->num_chunks);
if (!need_audio_header(fc, vsst)) {
max_group_bytes = k * max_slice_bytes;
g->num_header_slices = 0;
if (!need_audio_header(fc, vsst)) {
max_group_bytes = k * max_slice_bytes;
g->num_header_slices = 0;
- compute_group_size(vsst, g, max_group_bytes);
+ ret = compute_group_size(vsst, g, max_group_bytes);
+ if (ret < 0)
+ return ret;
g->slice_bytes = DIV_ROUND_UP(g->bytes, k);
if (g->slice_bytes == 0)
g->slice_bytes = 1;
g->slice_bytes = DIV_ROUND_UP(g->bytes, k);
if (g->slice_bytes == 0)
g->slice_bytes = 1;
h = vsst->header_len;
max_group_bytes = (k - num_slices(h, max_slice_bytes, n - k))
* max_slice_bytes;
h = vsst->header_len;
max_group_bytes = (k - num_slices(h, max_slice_bytes, n - k))
* max_slice_bytes;
- compute_group_size(vsst, g, max_group_bytes);
+ ret = compute_group_size(vsst, g, max_group_bytes);
+ if (ret < 0)
+ return ret;
d = g->bytes;
if (d == 0) {
g->slice_bytes = DIV_ROUND_UP(h, k);
d = g->bytes;
if (d == 0) {
g->slice_bytes = DIV_ROUND_UP(h, k);
* Setup data slices. Note that for ogg streams chunk 0 points to a
* buffer on the heap rather than to the mapped audio file.
*/
* Setup data slices. Note that for ogg streams chunk 0 points to a
* buffer on the heap rather than to the mapped audio file.
*/
- vss_get_chunk(g->first_chunk, vsst, &buf, &len);
+ ret = vss_get_chunk(g->first_chunk, vsst, &buf, &len);
+ if (ret < 0)
+ return ret;
for (p = buf; i < g->num_header_slices + data_slices; i++) {
if (p + g->slice_bytes > buf + g->bytes) {
/*
for (p = buf; i < g->num_header_slices + data_slices; i++) {
if (p + g->slice_bytes > buf + g->bytes) {
/*
*/
static void vss_send(struct vss_task *vsst)
{
*/
static void vss_send(struct vss_task *vsst)
{
bool fec_active = false;
struct timeval due;
struct fec_client *fc, *tmp_fc;
bool fec_active = false;
struct timeval due;
struct fec_client *fc, *tmp_fc;
mmd->events++;
set_mmd_offset();
}
mmd->events++;
set_mmd_offset();
}
- vss_get_chunk(mmd->current_chunk, vsst, &buf, &len);
- for (i = 0; senders[i].name; i++) {
+ ret = vss_get_chunk(mmd->current_chunk, vsst, &buf, &len);
+ if (ret < 0) {
+ PARA_ERROR_LOG("could not get chunk %lu: %s\n",
+ mmd->current_chunk, para_strerror(-ret));
+ } else {
/*
* We call ->send() even if len is zero because senders
* might have data queued which can be sent now.
*/
/*
* We call ->send() even if len is zero because senders
* might have data queued which can be sent now.
*/
- if (!senders[i].send)
- continue;
- senders[i].send(mmd->current_chunk, mmd->chunks_sent,
- buf, len, vsst->header_buf, vsst->header_len);
+ for (i = 0; senders[i].name; i++) {
+ if (!senders[i].send)
+ continue;
+ senders[i].send(mmd->current_chunk,
+ mmd->chunks_sent, buf, len,
+ vsst->header_buf, vsst->header_len);
+ }
}
mmd->chunks_sent++;
mmd->current_chunk++;
}
mmd->chunks_sent++;
mmd->current_chunk++;