avformat/utils: Change compute_chapters_end() from O(n²) to O(n log n)
Fixes: Timeout (49sec -> 9sec) Fixes: 27427/clusterfuzz-testcase-minimized-ffmpeg_dem_FFMETADATA_fuzzer-5140589838073856 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
		
							parent
							
								
									a454a0c14f
								
							
						
					
					
						commit
						ac5a568e6d
					
				| @ -3193,31 +3193,51 @@ enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag) | |||||||
|     return AV_CODEC_ID_NONE; |     return AV_CODEC_ID_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void compute_chapters_end(AVFormatContext *s) | static int chapter_start_cmp(const void *p1, const void *p2) | ||||||
| { | { | ||||||
|     unsigned int i, j; |     AVChapter *ch1 = *(AVChapter**)p1; | ||||||
|  |     AVChapter *ch2 = *(AVChapter**)p2; | ||||||
|  |     int delta = av_compare_ts(ch1->start, ch1->time_base, ch2->start, ch2->time_base); | ||||||
|  |     if (delta) | ||||||
|  |         return delta; | ||||||
|  |     return (ch1 > ch2) - (ch1 < ch2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int compute_chapters_end(AVFormatContext *s) | ||||||
|  | { | ||||||
|  |     unsigned int i; | ||||||
|     int64_t max_time = 0; |     int64_t max_time = 0; | ||||||
|  |     AVChapter **timetable = av_malloc(s->nb_chapters * sizeof(*timetable)); | ||||||
|  | 
 | ||||||
|  |     if (!timetable) | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
| 
 | 
 | ||||||
|     if (s->duration > 0 && s->start_time < INT64_MAX - s->duration) |     if (s->duration > 0 && s->start_time < INT64_MAX - s->duration) | ||||||
|         max_time = s->duration + |         max_time = s->duration + | ||||||
|                        ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); |                        ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < s->nb_chapters; i++) |     for (i = 0; i < s->nb_chapters; i++) | ||||||
|         if (s->chapters[i]->end == AV_NOPTS_VALUE) { |         timetable[i] = s->chapters[i]; | ||||||
|             AVChapter *ch = s->chapters[i]; |     qsort(timetable, s->nb_chapters, sizeof(*timetable), chapter_start_cmp); | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < s->nb_chapters; i++) | ||||||
|  |         if (timetable[i]->end == AV_NOPTS_VALUE) { | ||||||
|  |             AVChapter *ch = timetable[i]; | ||||||
|             int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, |             int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, | ||||||
|                                                 ch->time_base) |                                                 ch->time_base) | ||||||
|                                 : INT64_MAX; |                                 : INT64_MAX; | ||||||
| 
 | 
 | ||||||
|             for (j = 0; j < s->nb_chapters; j++) { |             if (i + 1 < s->nb_chapters) { | ||||||
|                 AVChapter *ch1     = s->chapters[j]; |                 AVChapter *ch1     = timetable[i + 1]; | ||||||
|                 int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, |                 int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, | ||||||
|                                                 ch->time_base); |                                                 ch->time_base); | ||||||
|                 if (j != i && next_start > ch->start && next_start < end) |                 if (next_start > ch->start && next_start < end) | ||||||
|                     end = next_start; |                     end = next_start; | ||||||
|             } |             } | ||||||
|             ch->end = (end == INT64_MAX || end < ch->start) ? ch->start : end; |             ch->end = (end == INT64_MAX || end < ch->start) ? ch->start : end; | ||||||
|         } |         } | ||||||
|  |     av_free(timetable); | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int get_std_framerate(int i) | static int get_std_framerate(int i) | ||||||
| @ -4073,7 +4093,9 @@ FF_ENABLE_DEPRECATION_WARNINGS | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     compute_chapters_end(ic); |     ret = compute_chapters_end(ic); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto find_stream_info_err; | ||||||
| 
 | 
 | ||||||
|     /* update the stream parameters from the internal codec contexts */ |     /* update the stream parameters from the internal codec contexts */ | ||||||
|     for (i = 0; i < ic->nb_streams; i++) { |     for (i = 0; i < ic->nb_streams; i++) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user