wtv: Seek by sector properly
Use an helper function to seek by sector to avoid possible mistakes due shifting by WTV_SECTOR_BITS a 32bit integer. Contrary to common intuition, a 32 bit integer left shifted by a 64 bit integer does not promote the 32 bit integer to 64 bit before shifting.
This commit is contained in:
		
							parent
							
								
									a27f1116cd
								
							
						
					
					
						commit
						2b72f8ac32
					
				| @ -48,10 +48,12 @@ | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #define WTV_SECTOR_BITS    INT64_C(12) | #define WTV_SECTOR_BITS    12 | ||||||
| #define WTV_SECTOR_SIZE    (1 << WTV_SECTOR_BITS) | #define WTV_SECTOR_SIZE    (1 << WTV_SECTOR_BITS) | ||||||
| #define WTV_BIGSECTOR_BITS 18 | #define WTV_BIGSECTOR_BITS 18 | ||||||
| 
 | 
 | ||||||
|  | #define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS) | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     AVIOContext *pb_filesystem;  /** file system (AVFormatContext->pb) */ |     AVIOContext *pb_filesystem;  /** file system (AVFormatContext->pb) */ | ||||||
| 
 | 
 | ||||||
| @ -64,6 +66,11 @@ typedef struct { | |||||||
|     int64_t length; |     int64_t length; | ||||||
| } WtvFile; | } WtvFile; | ||||||
| 
 | 
 | ||||||
|  | static int64_t seek_by_sector(AVIOContext *pb, int64_t sector, int64_t offset) | ||||||
|  | { | ||||||
|  |     return avio_seek(pb, SHIFT_SECTOR_BITS(sector) + offset, SEEK_SET); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @return bytes read, 0 on end of file, or <0 on error |  * @return bytes read, 0 on end of file, or <0 on error | ||||||
|  */ |  */ | ||||||
| @ -94,7 +101,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) | |||||||
|             int i = wf->position >> wf->sector_bits; |             int i = wf->position >> wf->sector_bits; | ||||||
|             if (i >= wf->nb_sectors || |             if (i >= wf->nb_sectors || | ||||||
|                 (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && |                 (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && | ||||||
|                 avio_seek(pb, wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { |                 seek_by_sector(pb, wf->sectors[i], 0) < 0)) { | ||||||
|                 wf->error = 1; |                 wf->error = 1; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| @ -119,8 +126,8 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence) | |||||||
|         offset = wf->length; |         offset = wf->length; | ||||||
| 
 | 
 | ||||||
|     wf->error = offset < 0 || offset >= wf->length || |     wf->error = offset < 0 || offset >= wf->length || | ||||||
|                 avio_seek(pb, (wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) |                 seek_by_sector(pb, wf->sectors[offset >> wf->sector_bits], | ||||||
|                               + (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0; |                                offset & ((1 << wf->sector_bits) - 1)) < 0; | ||||||
|     wf->position = offset; |     wf->position = offset; | ||||||
|     return offset; |     return offset; | ||||||
| } | } | ||||||
| @ -155,7 +162,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int | |||||||
|     WtvFile *wf; |     WtvFile *wf; | ||||||
|     uint8_t *buffer; |     uint8_t *buffer; | ||||||
| 
 | 
 | ||||||
|     if (avio_seek(s->pb, first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0) |     if (seek_by_sector(s->pb, first_sector, 0) < 0) | ||||||
|         return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|     wf = av_mallocz(sizeof(WtvFile)); |     wf = av_mallocz(sizeof(WtvFile)); | ||||||
| @ -184,14 +191,14 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int | |||||||
|         int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4); |         int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4); | ||||||
|         int i; |         int i; | ||||||
| 
 | 
 | ||||||
|         wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS); |         wf->sectors = av_malloc(SHIFT_SECTOR_BITS(nb_sectors1)); | ||||||
|         if (!wf->sectors) { |         if (!wf->sectors) { | ||||||
|             av_free(wf); |             av_free(wf); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|         wf->nb_sectors = 0; |         wf->nb_sectors = 0; | ||||||
|         for (i = 0; i < nb_sectors1; i++) { |         for (i = 0; i < nb_sectors1; i++) { | ||||||
|             if (avio_seek(s->pb, sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) |             if (seek_by_sector(s->pb, sectors1[i], 0) < 0) | ||||||
|                 break; |                 break; | ||||||
|             wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); |             wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); | ||||||
|         } |         } | ||||||
| @ -218,7 +225,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int | |||||||
| 
 | 
 | ||||||
|     /* seek to initial sector */ |     /* seek to initial sector */ | ||||||
|     wf->position = 0; |     wf->position = 0; | ||||||
|     if (avio_seek(s->pb, wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) { |     if (seek_by_sector(s->pb, wf->sectors[0], 0) < 0) { | ||||||
|         av_free(wf->sectors); |         av_free(wf->sectors); | ||||||
|         av_free(wf); |         av_free(wf); | ||||||
|         return NULL; |         return NULL; | ||||||
| @ -963,7 +970,7 @@ static int read_header(AVFormatContext *s) | |||||||
|     avio_skip(s->pb, 4); |     avio_skip(s->pb, 4); | ||||||
|     root_sector = avio_rl32(s->pb); |     root_sector = avio_rl32(s->pb); | ||||||
| 
 | 
 | ||||||
|     avio_seek(s->pb, root_sector << WTV_SECTOR_BITS, SEEK_SET); |     seek_by_sector(s->pb, root_sector, 0); | ||||||
|     root_size = avio_read(s->pb, root, root_size); |     root_size = avio_read(s->pb, root, root_size); | ||||||
|     if (root_size < 0) |     if (root_size < 0) | ||||||
|         return AVERROR_INVALIDDATA; |         return AVERROR_INVALIDDATA; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user