Commit 8c2da14d authored by conrad's avatar conrad

Mozilla #487519: Crash in vorbis_synthesis

Adds oggz_dlist cancellation, and uses that to bail out during
packet delivery if eg. header data is missing.
parent 7dd008d9
...@@ -138,17 +138,23 @@ oggz_dlist_prepend(OggzDList *dlist, void *elem) { ...@@ -138,17 +138,23 @@ oggz_dlist_prepend(OggzDList *dlist, void *elem) {
return 0; return 0;
} }
void int
oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func) { oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func) {
OggzDListElem *p; OggzDListElem *p;
for (p = dlist->head->next; p != dlist->tail; p = p->next) { for (p = dlist->head->next; p != dlist->tail; p = p->next) {
if (func(p->data) == DLIST_ITER_CANCEL) { int r = func(p->data);
if (r == DLIST_ITER_ERROR) {
return -1;
}
if (r == DLIST_ITER_CANCEL) {
break; break;
} }
} }
return 0;
} }
void void
...@@ -163,13 +169,19 @@ oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func) { ...@@ -163,13 +169,19 @@ oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func) {
} }
} }
void int
oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) { oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
OggzDListElem *p, *q; OggzDListElem *p, *q;
int result = 0;
for (p = dlist->head->next; p != dlist->tail; p = q) { for (p = dlist->head->next; p != dlist->tail; p = q) {
if (func(p->data) == DLIST_ITER_CANCEL) { int r = func(p->data);
if (r == DLIST_ITER_ERROR) {
result = -1;
}
if (r == DLIST_ITER_CANCEL) {
break; break;
} }
...@@ -179,7 +191,7 @@ oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) { ...@@ -179,7 +191,7 @@ oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
oggz_free(p); oggz_free(p);
} }
return result;
} }
void void
...@@ -191,7 +203,6 @@ oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) { ...@@ -191,7 +203,6 @@ oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
if (func(p->data) == DLIST_ITER_CANCEL) { if (func(p->data) == DLIST_ITER_CANCEL) {
break; break;
} }
q = p->prev; q = p->prev;
p->prev->next = p->next; p->prev->next = p->next;
p->next->prev = p->prev; p->next->prev = p->prev;
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
struct _OggzDList; struct _OggzDList;
typedef struct _OggzDList OggzDList; typedef struct _OggzDList OggzDList;
typedef enum {DLIST_ITER_CANCEL, DLIST_ITER_CONTINUE} OggzDListIterResponse; typedef enum {DLIST_ITER_ERROR=-1, DLIST_ITER_CANCEL=0, DLIST_ITER_CONTINUE=1} OggzDListIterResponse;
typedef OggzDListIterResponse (*OggzDListIterFunc) (void *elem); typedef OggzDListIterResponse (*OggzDListIterFunc) (void *elem);
...@@ -55,13 +55,13 @@ oggz_dlist_append(OggzDList *dlist, void *elem); ...@@ -55,13 +55,13 @@ oggz_dlist_append(OggzDList *dlist, void *elem);
int int
oggz_dlist_prepend(OggzDList *dlist, void *elem); oggz_dlist_prepend(OggzDList *dlist, void *elem);
void int
oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func); oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func);
void void
oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func); oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func);
void int
oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func); oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func);
void void
......
...@@ -304,11 +304,15 @@ oggz_read_deliver_packet(void *elem) { ...@@ -304,11 +304,15 @@ oggz_read_deliver_packet(void *elem) {
oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos); oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos);
if (p->stream->read_packet) { if (p->stream->read_packet) {
p->stream->read_packet(p->oggz, &(p->packet), p->serialno, if (p->stream->read_packet(p->oggz, &(p->packet), p->serialno,
p->stream->read_user_data); p->stream->read_user_data) != 0) {
return DLIST_ITER_ERROR;
}
} else if (p->reader->read_packet) { } else if (p->reader->read_packet) {
p->reader->read_packet(p->oggz, &(p->packet), p->serialno, if (p->reader->read_packet(p->oggz, &(p->packet), p->serialno,
p->reader->read_user_data); p->reader->read_user_data) != 0) {
return DLIST_ITER_ERROR;
}
} }
p->reader->current_granulepos = gp_stored; p->reader->current_granulepos = gp_stored;
...@@ -460,7 +464,9 @@ oggz_read_sync (OGGZ * oggz) ...@@ -460,7 +464,9 @@ oggz_read_sync (OGGZ * oggz)
ogg_int64_t gp_stored = stream->last_granulepos; ogg_int64_t gp_stored = stream->last_granulepos;
stream->last_packet = &packet; stream->last_packet = &packet;
oggz_dlist_reverse_iter(oggz->packet_buffer, oggz_read_update_gp); oggz_dlist_reverse_iter(oggz->packet_buffer, oggz_read_update_gp);
oggz_dlist_deliter(oggz->packet_buffer, oggz_read_deliver_packet); if (oggz_dlist_deliter(oggz->packet_buffer, oggz_read_deliver_packet) == -1) {
return OGGZ_ERR_HOLE_IN_DATA;
}
/* /*
* fix up the stream granulepos * fix up the stream granulepos
...@@ -498,7 +504,10 @@ oggz_read_sync (OGGZ * oggz) ...@@ -498,7 +504,10 @@ oggz_read_sync (OGGZ * oggz)
} }
/* If we've got a stop already, don't read more data in */ /* If we've got a stop already, don't read more data in */
if (cb_ret == OGGZ_STOP_OK || cb_ret == OGGZ_STOP_ERR) return cb_ret; if (cb_ret == OGGZ_STOP_OK ||
cb_ret == OGGZ_STOP_ERR ||
cb_ret == OGGZ_ERR_HOLE_IN_DATA)
return cb_ret;
if(oggz_read_get_next_page (oggz, &og) < 0) if(oggz_read_get_next_page (oggz, &og) < 0)
return OGGZ_READ_EMPTY; /* eof. leave uninitialized */ return OGGZ_READ_EMPTY; /* eof. leave uninitialized */
...@@ -600,8 +609,9 @@ oggz_read (OGGZ * oggz, long n) ...@@ -600,8 +609,9 @@ oggz_read (OGGZ * oggz, long n)
nread += bytes_read; nread += bytes_read;
cb_ret = oggz_read_sync (oggz); cb_ret = oggz_read_sync (oggz);
if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY) if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY || cb_ret == OGGZ_ERR_HOLE_IN_DATA) {
return cb_ret; return cb_ret;
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment