Opened 15 months ago
Last modified 15 months ago
#10474 new defect
Crash when vstack is used on two yuv420p streams with height not divisible by 2
Reported by: | André Martins | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avfilter |
Version: | git-master | Keywords: | |
Cc: | André Martins | Blocked By: | |
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
Out-of-bounds write (which often causes a crash) when vstack is used on two yuv420p streams with height not divisible by 2. Apparently, this only happens when the width is bigger than 64 (no errors for 64, errors for 65 and 66).
How to reproduce:
$ valgrind ./ffmpeg_g -v 9 -loglevel 99 -t 1 -f lavfi -i "testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack" -f null /dev/null ==21919== Memcheck, a memory error detector ==21919== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==21919== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info ==21919== Command: ./ffmpeg_g -v 9 -loglevel 99 -t 1 -f lavfi -i testsrc=s=100x55,format=yuv420p[a];\ testsrc=s=100x77,format=yuv420p[b];\ [a][b]vstack -f null /dev/null ==21919== ffmpeg version git-2023-07-16-36f4e6f8f4c Copyright (c) 2000-2023 the FFmpeg developers built with gcc 10 (Debian 10.2.1-6) configuration: --fatal-warnings --enable-gpl --enable-version3 --enable-nonfree --enable-libvpx --enable-libopus --enable-libx264 --enable-openssl --assert-level=1 --disable-doc libavutil 58. 14.100 / 58. 14.100 libavcodec 60. 22.100 / 60. 22.100 libavformat 60. 10.100 / 60. 10.100 libavdevice 60. 2.101 / 60. 2.101 libavfilter 9. 8.102 / 9. 8.102 libswscale 7. 3.100 / 7. 3.100 libswresample 4. 11.100 / 4. 11.100 libpostproc 57. 2.100 / 57. 2.100 Splitting the commandline. Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'. Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'. Reading option '-t' ... matched as option 't' (record or transcode "duration" seconds of audio/video) with argument '1'. Reading option '-f' ... matched as option 'f' (force format) with argument 'lavfi'. Reading option '-i' ... matched as input url with argument 'testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack'. Reading option '-f' ... matched as option 'f' (force format) with argument 'null'. Reading option '/dev/null' ... matched as output url. Finished splitting the commandline. Parsing a group of options: global . Applying option v (set logging level) with argument 9. Successfully parsed a group of options. Parsing a group of options: input url testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack. Applying option t (record or transcode "duration" seconds of audio/video) with argument 1. Applying option f (force format) with argument lavfi. Successfully parsed a group of options. Opening an input file: testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack. [AVFilterGraph @ 0x57114c0] Setting 's' to value '100x55' [AVFilterGraph @ 0x57114c0] Setting 'pix_fmts' to value 'yuv420p' [AVFilterGraph @ 0x57114c0] Setting 's' to value '100x77' [AVFilterGraph @ 0x57114c0] Setting 'pix_fmts' to value 'yuv420p' detected 8 logical cores [Parsed_testsrc_0 @ 0x57147c0] size:100x55 rate:25/1 duration:-1.000000 sar:1/1 [Parsed_testsrc_2 @ 0x5715a80] size:100x77 rate:25/1 duration:-1.000000 sar:1/1 [auto_scale_0 @ 0x571c140] w:iw h:ih flags:'' interl:0 [Parsed_format_1 @ 0x57153c0] auto-inserting filter 'auto_scale_0' between the filter 'Parsed_testsrc_0' and the filter 'Parsed_format_1' [auto_scale_1 @ 0x5753fc0] w:iw h:ih flags:'' interl:0 [Parsed_format_3 @ 0x5716680] auto-inserting filter 'auto_scale_1' between the filter 'Parsed_testsrc_2' and the filter 'Parsed_format_3' [AVFilterGraph @ 0x57114c0] query_formats: 6 queried, 3 merged, 2 already done, 0 delayed [auto_scale_0 @ 0x571c140] w:100 h:55 fmt:rgb24 sar:1/1 -> w:100 h:55 fmt:yuv420p sar:1/1 flags:0x00000004 [auto_scale_1 @ 0x5753fc0] w:100 h:77 fmt:rgb24 sar:1/1 -> w:100 h:77 fmt:yuv420p sar:1/1 flags:0x00000004 [Parsed_vstack_4 @ 0x5716d40] [framesync @ 0x5716fa8] Selected 1/25 time base [Parsed_vstack_4 @ 0x5716d40] [framesync @ 0x5716fa8] Sync level 1 ==21919== Thread 2: ==21919== Invalid write of size 8 ==21919== at 0x483F849: memmove (vg_replace_strmem.c:1270) ==21919== by 0x10A366D: image_copy_plane (imgutils.c:353) ==21919== by 0x10A366D: av_image_copy_plane (imgutils.c:378) ==21919== by 0x4661BE: process_slice (vf_stack.c:153) ==21919== by 0x325808: worker_func (pthread.c:49) ==21919== by 0x10BECAD: run_jobs (slicethread.c:65) ==21919== by 0x10BECAD: thread_worker (slicethread.c:89) ==21919== by 0x52E7EA6: start_thread (pthread_create.c:477) ==21919== by 0x53FEA2E: clone (clone.S:95) ==21919== Address 0x59d36a0 is 0 bytes after a block of size 4,256 alloc'd ==21919== at 0x483AEB8: memalign (vg_replace_malloc.c:906) ==21919== by 0x483AFCE: posix_memalign (vg_replace_malloc.c:1070) ==21919== by 0x10A753E: av_malloc (mem.c:105) ==21919== by 0x10920B5: av_buffer_alloc (buffer.c:82) ==21919== by 0x109211F: av_buffer_allocz (buffer.c:95) ==21919== by 0x1092814: pool_alloc_buffer (buffer.c:363) ==21919== by 0x1092814: av_buffer_pool_get (buffer.c:401) ==21919== by 0x321401: ff_frame_pool_get (framepool.c:217) ==21919== by 0x4CC22A: ff_default_get_video_buffer2 (video.c:87) ==21919== by 0x466049: process_frame (vf_stack.c:178) ==21919== by 0x32247F: ff_framesync_activate (framesync.c:364) ==21919== by 0x30EB04: ff_filter_activate (avfilter.c:1323) ==21919== by 0x312284: get_frame_internal (buffersink.c:137) ==21919== ==21919== Invalid write of size 2 ==21919== at 0x483F8A3: memmove (vg_replace_strmem.c:1270) ==21919== by 0x10A366D: image_copy_plane (imgutils.c:353) ==21919== by 0x10A366D: av_image_copy_plane (imgutils.c:378) ==21919== by 0x4661BE: process_slice (vf_stack.c:153) ==21919== by 0x325808: worker_func (pthread.c:49) ==21919== by 0x10BECAD: run_jobs (slicethread.c:65) ==21919== by 0x10BECAD: thread_worker (slicethread.c:89) ==21919== by 0x52E7EA6: start_thread (pthread_create.c:477) ==21919== by 0x53FEA2E: clone (clone.S:95) ==21919== Address 0x59d36b0 is 16 bytes after a block of size 4,256 alloc'd ==21919== at 0x483AEB8: memalign (vg_replace_malloc.c:906) ==21919== by 0x483AFCE: posix_memalign (vg_replace_malloc.c:1070) ==21919== by 0x10A753E: av_malloc (mem.c:105) ==21919== by 0x10920B5: av_buffer_alloc (buffer.c:82) ==21919== by 0x109211F: av_buffer_allocz (buffer.c:95) ==21919== by 0x1092814: pool_alloc_buffer (buffer.c:363) ==21919== by 0x1092814: av_buffer_pool_get (buffer.c:401) ==21919== by 0x321401: ff_frame_pool_get (framepool.c:217) ==21919== by 0x4CC22A: ff_default_get_video_buffer2 (video.c:87) ==21919== by 0x466049: process_frame (vf_stack.c:178) ==21919== by 0x32247F: ff_framesync_activate (framesync.c:364) ==21919== by 0x30EB04: ff_filter_activate (avfilter.c:1323) ==21919== by 0x312284: get_frame_internal (buffersink.c:137) ==21919== [lavfi @ 0x5710700] All info found [lavfi @ 0x5710700] stream 0: start_time: 0 duration: NOPTS [lavfi @ 0x5710700] format: start_time: 0 duration: NOPTS (estimate from bit rate) bitrate=0 kb/s Input #0, lavfi, from 'testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack': Duration: N/A, start: 0.000000, bitrate: N/A Stream #0:0, 1, 1/25: Video: wrapped_avframe, 1 reference frame, yuv420p, 100x132 [SAR 1:1 DAR 25:33], 0/1, 25 fps, 25 tbr, 25 tbn Successfully opened the file. Parsing a group of options: output url /dev/null. Applying option f (force format) with argument null. Successfully parsed a group of options. Opening an output file: /dev/null. [out#0/null @ 0x59d7680] No explicit maps, mapping streams automatically... [vost#0:0/wrapped_avframe @ 0x59d8780] Created video stream from input stream 0:0 Successfully opened the file. Stream mapping: Stream #0:0 -> #0:0 (wrapped_avframe (native) -> wrapped_avframe (native)) Press [q] to stop, [?] for help [graph 0 input from stream 0:0 @ 0x59f2e00] Setting 'video_size' to value '100x132' [graph 0 input from stream 0:0 @ 0x59f2e00] Setting 'pix_fmt' to value '0' [graph 0 input from stream 0:0 @ 0x59f2e00] Setting 'time_base' to value '1/25' [graph 0 input from stream 0:0 @ 0x59f2e00] Setting 'pixel_aspect' to value '1/1' [graph 0 input from stream 0:0 @ 0x59f2e00] Setting 'frame_rate' to value '25/1' [graph 0 input from stream 0:0 @ 0x59f2e00] w:100 h:132 pixfmt:yuv420p tb:1/25 fr:25/1 sar:1/1 [AVFilterGraph @ 0x59e2e00] query_formats: 4 queried, 3 merged, 0 already done, 0 delayed Output #0, null, to '/dev/null': Metadata: encoder : Lavf60.10.100 Stream #0:0, 0, 1/25: Video: wrapped_avframe, 1 reference frame, yuv420p(progressive), 100x132 (0x0) [SAR 1:1 DAR 25:33], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn Metadata: encoder : Lavc60.22.100 wrapped_avframe frame= 0 fps=0.0 q=-0.0 size= 0kB time=00:00:00.00 bitrate=N/A speed= 0x frame= 15 fps=0.0 q=-0.0 size=N/A time=00:00:00.60 bitrate=N/A speed= 1.2x [out_0_0 @ 0x59f4940] EOF on sink link out_0_0:default. No more output streams to write to, finishing. [vist#0:0/wrapped_avframe @ 0x59d6940] Decoder thread received EOF packet [vist#0:0/wrapped_avframe @ 0x59d6940] Decoder returned EOF, finishing [vist#0:0/wrapped_avframe @ 0x59d6940] Terminating decoder thread [out#0/null @ 0x59d7680] All streams finished [out#0/null @ 0x59d7680] Terminating muxer thread [out#0/null @ 0x59d7680] Output file #0 (/dev/null): [out#0/null @ 0x59d7680] Output stream #0:0 (video): 25 frames encoded; 25 packets muxed (12000 bytes); [out#0/null @ 0x59d7680] Total: 25 packets (12000 bytes) muxed [out#0/null @ 0x59d7680] video:12kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown frame= 25 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.96 bitrate=N/A speed=1.53x [in#0/lavfi @ 0x57104c0] Terminating demuxer thread [in#0/lavfi @ 0x57104c0] Input file #0 (testsrc=s=100x55,format=yuv420p[a]; testsrc=s=100x77,format=yuv420p[b]; [a][b]vstack): [in#0/lavfi @ 0x57104c0] Input stream #0:0 (video): 28 packets read (13440 bytes); 26 frames decoded; 0 decode errors; [in#0/lavfi @ 0x57104c0] Total: 28 packets (13440 bytes) demuxed ==21919== ==21919== HEAP SUMMARY: ==21919== in use at exit: 0 bytes in 0 blocks ==21919== total heap usage: 4,457 allocs, 4,457 frees, 2,752,452 bytes allocated ==21919== ==21919== All heap blocks were freed -- no leaks are possible ==21919== ==21919== For lists of detected and suppressed errors, rerun with: -s ==21919== ERROR SUMMARY: 224 errors from 2 contexts (suppressed: 0 from 0)
Note:
See TracTickets
for help on using tickets.
The crash is caused by chroma plane right shift.
for yuv420p,
the height of first input luma is 55, chroma height is obtained by AV_CEIL_RSHIFT which is 28;
the height of second input luma is 77, chroma height is 39.
the height of output luma is 132(55 + 77), then height of output chroma is 66 (132 >> 1)
66 < 67(28 + 39) so ffmpeg crashed...
The filter need check input parameters, especially height of input...