Changeset 1227

Show
Ignore:
Timestamp:
12/15/09 17:17:20 (3 months ago)
Author:
astrange
Message:

Fix incorrect behavior/crash with incomplete files in ff_dataref.

- The position could go past the end, in which case it would read a negative number of bytes and crash.
- It cached the file size at the start, but files being downloaded aren't locked and their size changes, so try to update it when it looks wrong.

Closes #446.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ff_dataref.c

    r969 r1227  
    3737/* DataRef Wrapper for QuickTime */ 
    3838 
    39 /* !!! THIS FUNCTION ASSUMES h->priv_data IS VALID in contrary to the other open functions 
    40 * found in ffmpeg */ 
    41 static int dataref_open(URLContext *h, const char *filename, int flags) 
    42 
    43         ComponentResult result; 
    44         dataref_private *private; 
     39static int dataref_update_filesize(dataref_private *private) 
     40
    4541        wide fsize; 
    46         long access = 0; 
    47          
    48         if(flags & URL_RDWR) { 
    49                 access = kDataHCanRead | kDataHCanWrite; 
    50         } else if(flags & URL_WRONLY) { 
    51                 access = kDataHCanWrite; 
    52         } else { 
    53                 access = kDataHCanRead; 
    54         } 
    55          
    56         private = h->priv_data; 
    57         result = OpenAComponent(GetDataHandler(private->dataRef, private->dataRefType, access), &private->dh); 
    58         require_noerr(result,bail); 
    59          
    60         result = DataHSetDataRef(private->dh, private->dataRef); 
    61         require_noerr(result,bail); 
    62          
    63         if(access & kDataHCanRead) { 
    64                 result = DataHOpenForRead(private->dh); 
    65                 require_noerr(result,bail); 
    66         } 
    67         if(access & kDataHCanWrite) { 
    68                 result = DataHOpenForWrite(private->dh); 
    69                 require_noerr(result,bail); 
    70         } 
    71          
    72         private->pos = 0ll; 
    73         private->size = 0ll; 
    74          
    75         result = DataHGetFileSize64(private->dh, &fsize); 
     42        ComponentResult result = DataHGetFileSize64(private->dh, &fsize); 
    7643        if(result == noErr) { 
    7744                private->size = (int64_t)fsize.lo; 
     
    8552                private->size = size32; 
    8653        } 
    87          
    88 bail: 
    89                 return result; 
     54bail: 
     55        return result; 
     56
     57 
     58/* !!! THIS FUNCTION ASSUMES h->priv_data IS VALID in contrary to the other open functions 
     59* found in ffmpeg */ 
     60static int dataref_open(URLContext *h, const char *filename, int flags) 
     61
     62        ComponentResult result; 
     63        dataref_private *private; 
     64        long access = 0; 
     65         
     66        if(flags & URL_RDWR) { 
     67                access = kDataHCanRead | kDataHCanWrite; 
     68        } else if(flags & URL_WRONLY) { 
     69                access = kDataHCanWrite; 
     70        } else { 
     71                access = kDataHCanRead; 
     72        } 
     73         
     74        private = h->priv_data; 
     75        result = OpenAComponent(GetDataHandler(private->dataRef, private->dataRefType, access), &private->dh); 
     76        require_noerr(result,bail); 
     77         
     78        result = DataHSetDataRef(private->dh, private->dataRef); 
     79        require_noerr(result,bail); 
     80         
     81        if(access & kDataHCanRead) { 
     82                result = DataHOpenForRead(private->dh); 
     83                require_noerr(result,bail); 
     84        } 
     85        if(access & kDataHCanWrite) { 
     86                result = DataHOpenForWrite(private->dh); 
     87                require_noerr(result,bail); 
     88        } 
     89         
     90        private->pos = 0ll; 
     91        private->size = 0ll; 
     92         
     93        result = dataref_update_filesize(private); 
     94        require_noerr(result,bail); 
     95bail: 
     96        return result; 
    9097} /* dataref_open() */ 
    9198 
     
    93100{ 
    94101        int result; 
    95         int64_t read; 
    96  
    97         dataref_private *p = (dataref_private*)h->priv_data; 
    98          
    99         read = p->size - p->pos; 
    100         read = (read < size) ? read : size; 
     102        dataref_private *p = (dataref_private*)h->priv_data; 
     103        int read; 
     104 
     105        if (p->pos + size > p->size) { 
     106                // it tried to read past the end 
     107                // but since we cache the size, it might be wrong 
     108                // try to update the size before clipping the request 
     109                dataref_update_filesize(p); 
     110        } 
     111         
     112        if (p->pos >= p->size) 
     113                return 0; // can't read past the end 
     114        else 
     115                read = FFMIN(size, p->size - p->pos); 
    101116         
    102117        if(p->supportsWideOffsets) { 
     
    163178                        break; 
    164179                case SEEK_END: 
     180                        dataref_update_filesize(p); 
    165181                        p->pos = p->size + pos; 
    166182                        break; 
    167183                case AVSEEK_SIZE: 
     184                        dataref_update_filesize(p); 
    168185                        return p->size; 
    169186                default: