#7084: Memory leak in libavfilter/graphparser.c
-------------------------------------+-------------------------------------
             Reporter:  Kira         |                     Type:  defect
               Status:  new          |                 Priority:  normal
            Component:  avfilter     |                  Version:
             Keywords:  memory       |  unspecified
  leak, parse_outputs                |               Blocked By:
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
 parse_outputs from libavfilter/graphparser.c
 {{{
 #!div style="font-size: 80%"
   {{{#!C
  static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
                          AVFilterInOut **open_inputs,
                          AVFilterInOut **open_outputs, void *log_ctx)
 {
     int ret, pad = 0;

     while (**buf == '[') {
         char *name = parse_link_name(buf, log_ctx);
         AVFilterInOut *match;

         AVFilterInOut *input = *curr_inputs;

         if (!name)
             return AVERROR(EINVAL);

         if (!input) {
             av_log(log_ctx, AV_LOG_ERROR,
                    "No output pad can be associated to link label
 '%s'.\n", name);
             av_free(name);
             return AVERROR(EINVAL);
         }
         *curr_inputs = (*curr_inputs)->next;

         /* First check if the label is not in the open_inputs list */
         match = extract_inout(name, open_inputs);

         if (match) {
             if ((ret = link_filter(input->filter_ctx, input->pad_idx,
                                    match->filter_ctx, match->pad_idx,
 log_ctx)) < 0) {
                 av_free(name);
                 return ret;
             }
             av_freep(&match->name);
             av_freep(&name);
             av_freep(&match);
             av_freep(&input);
         } else {
             /* Not in the list, so add the first input as an open_output
 */
             input->name = name;
             insert_inout(open_outputs, input);
         }
         *buf += strspn(*buf, WHITESPACES);
         pad++;
     }

     return pad;
 }
   }}}
 }}}
 line 361:
 match = extract_inout(name, open_inputs);
 Extract a node from the linked list open_inputs, the origin linked list
 changed here.
 extract_inout from libavfilter/graphparser.c
 {{{
 #!div style="font-size: 80%"
   {{{#!C
 static AVFilterInOut *extract_inout(const char *label, AVFilterInOut
 **links)
 {
     AVFilterInOut *ret;

     // find the first node whose name is same as label.
     while (*links && (!(*links)->name || strcmp((*links)->name, label)))
         links = &((*links)->next);

     ret = *links;

     if (ret) {  // off the chain
         *links = ret->next;
         ret->next = NULL;
     }

     return ret;
 }
   }}}
 }}}

 If the match found, we enter here.
 {{{
 #!div style="font-size: 80%"
   {{{#!C
 if (match) {
             if ((ret = link_filter(input->filter_ctx, input->pad_idx,
                                    match->filter_ctx, match->pad_idx,
 log_ctx)) < 0) {
                 av_free(name);
                 return ret;
             }
             av_freep(&match->name);
             av_freep(&name);
             av_freep(&match);
             av_freep(&input);
         }
   }}}
 }}}

 If the link_filter call fails, the variable match will never be freed!

 So the memory leak happens here.

 Compile the leak_poc.c

 Run it and use htop or something else to monitor the memory consumption of
 the process. You will see the leak.

--
Ticket URL: <https://trac.ffmpeg.org/ticket/7084>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
_______________________________________________
FFmpeg-trac mailing list
FFmpeg-trac@avcodec.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-trac

Reply via email to