Fix free of uninitialized memory if seek fails in ov_raw_seek
[platform/upstream/libvorbis.git] / lib / vorbisfile.c
index 1b7f80a..831cb39 100644 (file)
@@ -5,13 +5,12 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2014             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id$
 
  ********************************************************************/
 
@@ -438,9 +437,11 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
     while((result=ogg_stream_packetout(&vf->os,&op))){
       if(result>0){ /* ignore holes */
         long thisblock=vorbis_packet_blocksize(vi,&op);
-        if(lastblock!=-1)
-          accumulated+=(lastblock+thisblock)>>2;
-        lastblock=thisblock;
+        if(thisblock>=0){
+          if(lastblock!=-1)
+            accumulated+=(lastblock+thisblock)>>2;
+          lastblock=thisblock;
+        }
       }
     }
 
@@ -1229,7 +1230,6 @@ double ov_time_total(OggVorbis_File *vf,int i){
 
 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
   ogg_stream_state work_os;
-  int ret;
 
   if(vf->ready_state<OPENED)return(OV_EINVAL);
   if(!vf->seekable)
@@ -1252,8 +1252,12 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
                             vf->current_serialno); /* must set serialno */
   vorbis_synthesis_restart(&vf->vd);
 
-  ret=_seek_helper(vf,pos);
-  if(ret)goto seek_error;
+  if(_seek_helper(vf,pos)) {
+    /* dump the machine so we're in a known state */
+    vf->pcm_offset=-1;
+    _decode_clear(vf);
+    return OV_EBADLINK;
+  }
 
   /* we need to make sure the pcm_offset is set, but we don't want to
      advance the raw cursor past good packets just to get to the first
@@ -1387,13 +1391,6 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
   vf->bittrack=0.f;
   vf->samptrack=0.f;
   return(0);
-
- seek_error:
-  /* dump the machine so we're in a known state */
-  vf->pcm_offset=-1;
-  ogg_stream_clear(&work_os);
-  _decode_clear(vf);
-  return OV_EBADLINK;
 }
 
 /* Page granularity seek (faster than sample granularity because we
@@ -1437,8 +1434,21 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
     ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
     ogg_int64_t target=pos-total+begintime;
     ogg_int64_t best=-1;
+    int         got_page=0;
 
     ogg_page og;
+
+    /* if we have only one page, there will be no bisection.  Grab the page here */
+    if(begin==end){
+      result=_seek_helper(vf,begin);
+      if(result) goto seek_error;
+
+      result=_get_next_page(vf,&og,1);
+      if(result<0) goto seek_error;
+
+      got_page=1;
+    }
+
     /* bisection loop */
     while(begin<end){
       ogg_int64_t bisect;
@@ -1482,6 +1492,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
           }
         }else{
           ogg_int64_t granulepos;
+          got_page=1;
 
           /* got a page. analyze it */
           /* only consider pages from primary vorbis stream */
@@ -1544,7 +1555,8 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
          bisection would 'fail' because our search target was before the
          first PCM granule position fencepost. */
 
-      if(begin == vf->dataoffsets[link] &&
+      if(got_page &&
+         begin == vf->dataoffsets[link] &&
          ogg_page_serialno(&og)==vf->serialnos[link]){
 
         /* Yes, this is the beginning-of-stream case. We already have