Bug 487519. Detect more Vorbis errors and propagate them out. rs=roc
authorChris Double <chris.double@double.co.nz>
Tue, 02 Jun 2009 09:20:51 +1200
changeset 28870 b0766717ce73ca814cd50641d16c6bc76e4dda7b
parent 28869 6a07f00fbfb263577160cac0e1fa44af0fad472f
child 28871 cf03f9d5bd95d751c89d149913fed9cac87cc61d
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs487519
milestone1.9.2a1pre
Bug 487519. Detect more Vorbis errors and propagate them out. rs=roc
media/libfishsound/README_MOZILLA
media/libfishsound/bug487519.patch
media/libfishsound/src/libfishsound/fishsound_vorbis.c
media/libfishsound/update.sh
media/liboggplay/README_MOZILLA
media/liboggplay/bug487519.patch
media/liboggplay/src/liboggplay/oggplay_callback.c
media/liboggplay/update.sh
media/liboggz/README_MOZILLA
media/liboggz/bug487519.patch
media/liboggz/src/liboggz/oggz_dlist.c
media/liboggz/src/liboggz/oggz_dlist.h
media/liboggz/src/liboggz/oggz_read.c
media/liboggz/update.sh
media/libvorbis/README_MOZILLA
media/libvorbis/bug487519.patch
media/libvorbis/lib/vorbis_synthesis.c
media/libvorbis/update.sh
--- a/media/libfishsound/README_MOZILLA
+++ b/media/libfishsound/README_MOZILLA
@@ -4,8 +4,10 @@ were those applied by update.sh and the 
 files for the Mozilla build system.
 
 Some files are renamed during the copy to prevent clashes with object
 file names with other Mozilla libraries.
 
 The git commit id used was e98a05 from git://git.xiph.org/libfishsound.git
 
 endian.patch is applied to fix Bug 45269.
+
+bug487519.patch: Fixes for bug487519
new file mode 100644
--- /dev/null
+++ b/media/libfishsound/bug487519.patch
@@ -0,0 +1,20 @@
+diff --git a/media/libfishsound/src/libfishsound/fishsound_vorbis.c b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
+index 68bdb3a..236dda4 100644
+--- a/media/libfishsound/src/libfishsound/fishsound_vorbis.c
++++ b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
+@@ -154,9 +154,13 @@ fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
+   } else {
+     FishSoundDecoded_FloatIlv df;
+     FishSoundDecoded_Float dfi;
+-
+-    if (vorbis_synthesis (&fsv->vb, &op) == 0)
++    int r;
++    if ((r = vorbis_synthesis (&fsv->vb, &op)) == 0) 
+       vorbis_synthesis_blockin (&fsv->vd, &fsv->vb);
++    
++    if (r == OV_EBADPACKET) {
++      return FISH_SOUND_ERR_GENERIC;
++    }
+ 
+     while ((samples = vorbis_synthesis_pcmout (&fsv->vd, &fsv->pcm)) > 0) {
+       vorbis_synthesis_read (&fsv->vd, samples);
--- a/media/libfishsound/src/libfishsound/fishsound_vorbis.c
+++ b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
@@ -149,19 +149,23 @@ fs_vorbis_decode (FishSound * fsound, un
       }
     } else if (fsv->packetno == 2) {
       vorbis_synthesis_init (&fsv->vd, &fsv->vi);
       vorbis_block_init (&fsv->vd, &fsv->vb);
     }
   } else {
     FishSoundDecoded_FloatIlv df;
     FishSoundDecoded_Float dfi;
-
-    if (vorbis_synthesis (&fsv->vb, &op) == 0)
+    int r;
+    if ((r = vorbis_synthesis (&fsv->vb, &op)) == 0) 
       vorbis_synthesis_blockin (&fsv->vd, &fsv->vb);
+    
+    if (r == OV_EBADPACKET) {
+      return FISH_SOUND_ERR_GENERIC;
+    }
 
     while ((samples = vorbis_synthesis_pcmout (&fsv->vd, &fsv->pcm)) > 0) {
       vorbis_synthesis_read (&fsv->vd, samples);
 
       if (fsound->frameno != -1)
 	fsound->frameno += samples;
 
       if (fsound->interleave) {
--- a/media/libfishsound/update.sh
+++ b/media/libfishsound/update.sh
@@ -34,8 +34,9 @@ cp $1/src/libfishsound/private.h ./src/l
 cp $1/src/libfishsound/fs_compat.h ./src/libfishsound/fs_compat.h
 cp $1/src/libfishsound/speex.c ./src/libfishsound/fishsound_speex.c
 cp $1/src/libfishsound/encode.c ./src/libfishsound/fishsound_encode.c
 cp $1/src/libfishsound/fs_vector.h ./src/libfishsound/fs_vector.h
 cp $1/src/libfishsound/fs_vector.c ./src/libfishsound/fs_vector.c
 cp $1/src/libfishsound/convert.h ./src/libfishsound/convert.h
 cp $1/AUTHORS ./AUTHORS
 patch -p3 <endian.patch
+patch -p3 <bug487519.patch
--- a/media/liboggplay/README_MOZILLA
+++ b/media/liboggplay/README_MOZILLA
@@ -32,8 +32,10 @@ bug488951: Fix for YUV conversion for od
 bug488951_fix_yuv: Additional fixes to YUV conversion that have not been
                    upstreamed yet.
 
 bug488951_fix_yuv_2: Additional fix to YUV conversion for odd height videos
                      that has not been upstreamed yet.
 
 bug495129a.patch: Fix from liboggplay commit 6c8e11.
 bug495129b.patch: Fix from liboggplay commit 3602bf.
+
+bug487519.patch: Fix for bug 487519.
new file mode 100644
--- /dev/null
+++ b/media/liboggplay/bug487519.patch
@@ -0,0 +1,19 @@
+diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
+index 428faee..344599a 100644
+--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
++++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
+@@ -388,7 +388,13 @@ oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
+ 
+   fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
+                                                                 op->e_o_s);
+-  fish_sound_decode (decoder->sound_handle, op->packet, op->bytes);
++  if (fish_sound_decode (decoder->sound_handle, op->packet, op->bytes) != 0) {
++    // Unrecoverable error, disable track
++    op->e_o_s = 1;
++    common->active = 0;
++    common->player->active_tracks--;
++    return OGGZ_ERR_HOLE_IN_DATA;
++  }
+ 
+   if (decoder->sound_info.channels == 0) {
+     fish_sound_command(decoder->sound_handle, FISH_SOUND_GET_INFO,
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -383,17 +383,23 @@ oggplay_callback_audio (OGGZ * oggz, ogg
   if (granulepos > 0 && (!decoder->decoder.active)) {
     return 0;
   }
 
   common->last_granulepos = granulepos;
 
   fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
                                                                 op->e_o_s);
-  fish_sound_decode (decoder->sound_handle, op->packet, op->bytes);
+  if (fish_sound_decode (decoder->sound_handle, op->packet, op->bytes) != 0) {
+    // Unrecoverable error, disable track
+    op->e_o_s = 1;
+    common->active = 0;
+    common->player->active_tracks--;
+    return OGGZ_ERR_HOLE_IN_DATA;
+  }
 
   if (decoder->sound_info.channels == 0) {
     fish_sound_command(decoder->sound_handle, FISH_SOUND_GET_INFO,
                     &(decoder->sound_info), sizeof(FishSoundInfo));
   }
 
   if (op->e_o_s) {
     common->active = 0;
--- a/media/liboggplay/update.sh
+++ b/media/liboggplay/update.sh
@@ -53,8 +53,9 @@ patch -p3 < aspect_ratio.patch
 patch -p3 < bug493678.patch
 patch -p1 < bug493224.patch
 patch -p3 < seek_to_key_frame.patch
 patch -p3 < bug488951.patch
 patch -p3 < bug488951_yuv_fix.patch
 patch -p3 < bug488951_yuv_fix_2.patch
 patch -p3 < bug495129a.patch
 patch -p3 < bug495129b.patch
+patch -p3 < bug487519.patch
--- a/media/liboggz/README_MOZILLA
+++ b/media/liboggz/README_MOZILLA
@@ -11,8 +11,10 @@ see bug 461844 for details.
 
 endian.patch is applied to fix bug 452698.
 
 bounded_seek.patch is applied to fix bug 469408.
 
 key_frame_seek.patch fixes bug 463358.
 
 offset_next.patch fixes bug 495366.
+
+bug487519.patch: Fix for bug 487519.
new file mode 100644
--- /dev/null
+++ b/media/liboggz/bug487519.patch
@@ -0,0 +1,156 @@
+diff --git a/media/liboggz/src/liboggz/oggz_dlist.c b/media/liboggz/src/liboggz/oggz_dlist.c
+index 7b26070..541563a 100644
+--- a/media/liboggz/src/liboggz/oggz_dlist.c
++++ b/media/liboggz/src/liboggz/oggz_dlist.c
+@@ -142,17 +142,23 @@ oggz_dlist_prepend(OggzDList *dlist, void *elem) {
+   return 0;
+ }
+ 
+-void
++int
+ oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func) {
+ 
+   OggzDListElem *p;
+ 
+   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;
+     }
+   }
+ 
++  return 0;
+ }
+ 
+ void
+@@ -167,13 +173,19 @@ oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func) {
+   }
+ }
+ 
+-void
++int
+ oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
+ 
+   OggzDListElem *p, *q;
++  int result = 0;
+ 
+   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;
+     }
+ 
+@@ -183,7 +195,7 @@ oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
+ 
+     oggz_free(p);
+   }
+-
++  return result;
+ }
+ 
+ void
+@@ -195,7 +207,6 @@ oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
+     if (func(p->data) == DLIST_ITER_CANCEL) {
+       break;
+     }
+-
+     q = p->prev;
+     p->prev->next = p->next;
+     p->next->prev = p->prev;
+diff --git a/media/liboggz/src/liboggz/oggz_dlist.h b/media/liboggz/src/liboggz/oggz_dlist.h
+index 8913e73..8955250 100644
+--- a/media/liboggz/src/liboggz/oggz_dlist.h
++++ b/media/liboggz/src/liboggz/oggz_dlist.h
+@@ -36,7 +36,7 @@
+ struct _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);
+ 
+@@ -55,13 +55,13 @@ oggz_dlist_append(OggzDList *dlist, void *elem);
+ int
+ oggz_dlist_prepend(OggzDList *dlist, void *elem);
+ 
+-void
++int
+ oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func);
+ 
+ void
+ oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func);
+ 
+-void
++int
+ oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func);
+ 
+ void
+diff --git a/media/liboggz/src/liboggz/oggz_read.c b/media/liboggz/src/liboggz/oggz_read.c
+index 81eeb9e..98e25e8 100644
+--- a/media/liboggz/src/liboggz/oggz_read.c
++++ b/media/liboggz/src/liboggz/oggz_read.c
+@@ -295,11 +295,15 @@ oggz_read_deliver_packet(void *elem) {
+     oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos);
+ 
+   if (p->stream->read_packet) {
+-    p->stream->read_packet(p->oggz, &(p->packet), p->serialno, 
+-            p->stream->read_user_data);
++    if (p->stream->read_packet(p->oggz, &(p->packet), p->serialno, 
++			       p->stream->read_user_data) != 0) {
++      return DLIST_ITER_ERROR;
++    }
+   } else if (p->reader->read_packet) {
+-    p->reader->read_packet(p->oggz, &(p->packet), p->serialno, 
+-            p->reader->read_user_data);
++    if (p->reader->read_packet(p->oggz, &(p->packet), p->serialno, 
++			       p->reader->read_user_data) != 0) {
++      return DLIST_ITER_ERROR;
++    }
+   }
+ 
+   p->reader->current_granulepos = gp_stored;
+@@ -455,7 +459,9 @@ oggz_read_sync (OGGZ * oggz)
+               ogg_int64_t gp_stored = stream->last_granulepos;
+               stream->last_packet = &packet;
+               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 
+@@ -493,7 +499,10 @@ oggz_read_sync (OGGZ * oggz)
+     }
+ 
+     /* 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)
+       return OGGZ_READ_EMPTY; /* eof. leave uninitialized */
+@@ -595,8 +604,9 @@ oggz_read (OGGZ * oggz, long n)
+       nread += bytes_read;
+       
+       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;
++      }
+     }
+   }
+ 
--- a/media/liboggz/src/liboggz/oggz_dlist.c
+++ b/media/liboggz/src/liboggz/oggz_dlist.c
@@ -137,70 +137,81 @@ oggz_dlist_prepend(OggzDList *dlist, voi
   new_elem->prev = dlist->head;
   new_elem->next = dlist->head->next;
   new_elem->prev->next = new_elem;
   new_elem->next->prev = new_elem;
 
   return 0;
 }
 
-void
+int
 oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p;
 
   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;
     }
   }
 
+  return 0;
 }
 
 void
 oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p;
 
   for (p = dlist->tail->prev; p != dlist->head; p = p->prev) {
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
   }
 }
 
-void
+int
 oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p, *q;
+  int result = 0;
 
   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;
     }
 
     q = p->next;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 
     oggz_free(p);
   }
-
+  return result;
 }
 
 void
 oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p, *q;
 
   for (p = dlist->tail->prev; p != dlist->head; p = q) {
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
-
     q = p->prev;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 
     oggz_free(p);
   }
 
 }
--- a/media/liboggz/src/liboggz/oggz_dlist.h
+++ b/media/liboggz/src/liboggz/oggz_dlist.h
@@ -31,17 +31,17 @@
 */
 
 #ifndef __OGGZ_DLIST_H__
 #define __OGGZ_DLIST_H__
 
 struct _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);
 
 OggzDList *
 oggz_dlist_new (void);
 
 void
 oggz_dlist_delete(OggzDList *dlist);
@@ -50,21 +50,21 @@ int
 oggz_dlist_is_empty(OggzDList *dlist);
 
 int
 oggz_dlist_append(OggzDList *dlist, void *elem);
 
 int
 oggz_dlist_prepend(OggzDList *dlist, void *elem);
 
-void
+int
 oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func);
 
 void
 oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func);
 
-void
+int
 oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func);
 
 void
 oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func);
 
 #endif
--- a/media/liboggz/src/liboggz/oggz_read.c
+++ b/media/liboggz/src/liboggz/oggz_read.c
@@ -290,21 +290,25 @@ oggz_read_deliver_packet(void *elem) {
   unit_stored = p->reader->current_unit;
 
   p->reader->current_granulepos = p->calced_granulepos;
 
   p->reader->current_unit =
     oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos);
 
   if (p->stream->read_packet) {
-    p->stream->read_packet(p->oggz, &(p->packet), p->serialno, 
-            p->stream->read_user_data);
+    if (p->stream->read_packet(p->oggz, &(p->packet), p->serialno, 
+			       p->stream->read_user_data) != 0) {
+      return DLIST_ITER_ERROR;
+    }
   } else if (p->reader->read_packet) {
-    p->reader->read_packet(p->oggz, &(p->packet), p->serialno, 
-            p->reader->read_user_data);
+    if (p->reader->read_packet(p->oggz, &(p->packet), p->serialno, 
+			       p->reader->read_user_data) != 0) {
+      return DLIST_ITER_ERROR;
+    }
   }
 
   p->reader->current_granulepos = gp_stored;
   p->reader->current_unit = unit_stored;
 
   oggz_read_free_pbuffer_entry(p);
 
   return DLIST_ITER_CONTINUE;
@@ -450,17 +454,19 @@ oggz_read_sync (OGGZ * oggz)
                * move backward through the list assigning gp values based upon
                * the granulepos we just recieved.  Then move forward through
                * the list delivering any packets at the beginning with valid
                * gp values
                */
               ogg_int64_t gp_stored = stream->last_granulepos;
               stream->last_packet = &packet;
               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 
                */
               stream->last_granulepos = gp_stored;
 
               if (!oggz_dlist_is_empty(oggz->packet_buffer)) {
                 OggzBufferedPacket *p = oggz_read_new_pbuffer_entry(
@@ -488,17 +494,20 @@ oggz_read_sync (OGGZ * oggz)
           if (!op->b_o_s) stream->delivered_non_b_o_s = 1;
         }
         else
           break;
       }
     }
 
     /* 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)
       return OGGZ_READ_EMPTY; /* eof. leave uninitialized */
 
     serialno = ogg_page_serialno (&og);
     reader->current_serialno = serialno; /* XXX: maybe not necessary */
 
     stream = oggz_get_stream (oggz, serialno);
@@ -590,18 +599,19 @@ oggz_read (OGGZ * oggz, long n)
 
     if (bytes_read > 0) {
       ogg_sync_wrote (&reader->ogg_sync, bytes_read);
       
       remaining -= bytes_read;
       nread += bytes_read;
       
       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;
+      }
     }
   }
 
   if (cb_ret == OGGZ_STOP_ERR) oggz_purge (oggz);
 
   /* Don't return 0 unless it's actually an EOF condition */
   if (nread == 0) {
     switch (bytes_read) {
--- a/media/liboggz/update.sh
+++ b/media/liboggz/update.sh
@@ -44,8 +44,9 @@ sed s/\#include\ \"config.h\"/\#ifdef\ W
 cp $1/src/liboggz/dirac.h ./src/liboggz/dirac.h
 sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/dirac.c >./src/liboggz/dirac.c
 cp $1/AUTHORS ./AUTHORS
 patch -p3 <wince.patch
 patch -p3 <endian.patch
 patch -p3 <bounded_seek.patch
 patch -p3 <key_frame_seek.patch
 patch -p3 <offset_next.patch
+patch -p3 <bug487519.patch
--- a/media/libvorbis/README_MOZILLA
+++ b/media/libvorbis/README_MOZILLA
@@ -6,8 +6,9 @@ files for the Mozilla build system.
 Some files are renamed during the copy to prevent clashes with object
 file names with other Mozilla libraries.
 
 BUG 455372 - WinCE LibVorbis No FPU Support on WinMobile, removed FPU
 support for builds with WINCE defined.
 
 BUG 469639 - Failed to build firefox trunk on OpenSolaris
 bug481601.patch is appled to fix bug 481601.
+bug487519.patch: fix for bug 487519.
new file mode 100644
--- /dev/null
+++ b/media/libvorbis/bug487519.patch
@@ -0,0 +1,20 @@
+diff --git a/media/libvorbis/lib/vorbis_synthesis.c b/media/libvorbis/lib/vorbis_synthesis.c
+index 8872f57..b7b2399 100644
+--- a/media/libvorbis/lib/vorbis_synthesis.c
++++ b/media/libvorbis/lib/vorbis_synthesis.c
+@@ -43,9 +43,14 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
+ 
+   /* read our mode and pre/post windowsize */
+   mode=oggpack_read(opb,b->modebits);
+-  if(mode==-1)return(OV_EBADPACKET);
++  if(mode==-1) {
++    return(OV_EBADPACKET);
++  }
+   
+   vb->mode=mode;
++  if(!ci->mode_param[mode]) {
++    return(OV_EBADPACKET); 
++  }
+   vb->W=ci->mode_param[mode]->blockflag;
+   if(vb->W){
+ 
--- a/media/libvorbis/lib/vorbis_synthesis.c
+++ b/media/libvorbis/lib/vorbis_synthesis.c
@@ -38,19 +38,24 @@ int vorbis_synthesis(vorbis_block *vb,og
   /* Check the packet type */
   if(oggpack_read(opb,1)!=0){
     /* Oops.  This is not an audio data packet */
     return(OV_ENOTAUDIO);
   }
 
   /* read our mode and pre/post windowsize */
   mode=oggpack_read(opb,b->modebits);
-  if(mode==-1)return(OV_EBADPACKET);
+  if(mode==-1) {
+    return(OV_EBADPACKET);
+  }
   
   vb->mode=mode;
+  if(!ci->mode_param[mode]) {
+    return(OV_EBADPACKET); 
+  }
   vb->W=ci->mode_param[mode]->blockflag;
   if(vb->W){
 
     /* this doesn;t get mapped through mode selection as it's used
        only for window selection */
     vb->lW=oggpack_read(opb,1);
     vb->nW=oggpack_read(opb,1);
     if(vb->nW==-1)   return(OV_EBADPACKET);
--- a/media/libvorbis/update.sh
+++ b/media/libvorbis/update.sh
@@ -43,8 +43,9 @@ cp $1/lib/bitrate.c ./lib/vorbis_bitrate
 cp $1/lib/block.c ./lib/vorbis_block.c
 cp $1/include/vorbis/codec.h ./include/vorbis/codec.h
 cp $1/todo.txt ./todo.txt
 cp $1/COPYING ./COPYING
 cp $1/README ./README
 cp $1/AUTHORS ./AUTHORS
 patch -p3 < ./alloca.diff
 patch -p3 <./bug481601.patch
+patch -p3 <bug487519.patch