Skip to content

Possible AVFormatContext leak in MediaInfoWorker::Execute #3

Description

@OvOhao

Possible AVFormatContext leak in MediaInfoWorker::Execute

I found a possible per-operation resource leak in MediaInfoWorker::Execute. The worker allocates and
opens an AVFormatContext (which owns an open file/IO handle and demuxer state). If
avformat_find_stream_info fails, the worker only calls SetError and returns — it never closes the
already-opened context. MediaInfoWorker has no destructor and OnError just rejects the promise, so
on this path the opened AVFormatContext (and its file/socket handle) is leaked for every failed call.
Ownership is only transferred to a self-freeing wrapper on the success path (OnOK), never on error.

File: src/media-info-worker.cc

Function: MediaInfoWorker::Execute (and MediaInfoWorker::OnError)

void MediaInfoWorker::Execute() {
    avFormatContext = avformat_alloc_context();
    if (!avFormatContext) { SetError("..."); return; }

    int openStatus = avformat_open_input(&avFormatContext, fileName.c_str(), NULL, options);
    if (openStatus < 0) { SetError("filePath could not be opened"); return; }  // ffmpeg frees ctx here

    if (avformat_find_stream_info(avFormatContext, NULL) < 0) {
        Napi::AsyncWorker::SetError("could not get stream info");
        // <-- returns with avFormatContext still OPEN and never closed
    }
}

void MediaInfoWorker::OnError(const Napi::Error& error) {
    deferred.Reject(error.Value());   // avFormatContext is never closed on the error path
}
  1. avformat_alloc_context() + a successful avformat_open_input leave avFormatContext pointing at
    an opened input (file/IO handle + demuxer). (On avformat_open_input failure FFmpeg frees the
    context itself, so that branch is fine.)
  2. When avformat_find_stream_info returns < 0 — reachable with a truncated/corrupt but openable
    media file — Execute sets the error and returns without calling avformat_close_input.
  3. MediaInfoWorker has no destructor and OnError only rejects the promise. The success path
    (OnOK) is the only place that hands the pointer to an AvFormatContext ObjectWrap whose
    ~AvFormatContext calls avformat_close_input. On the error path that handoff never happens, so
    the context and its underlying handle leak once per failed getFileInfo call.

JS trigger:

const { getFileInfo } = require('@alex8088/node-ffprobe');
// a file that opens but whose stream info cannot be parsed (corrupt/truncated) rejects,
// leaking one AVFormatContext + file handle each time:
for (let i = 0; i < 10000; i++) {
  getFileInfo('./corrupt-but-openable.bin').catch(() => {});
}

Suggested fix: close the context on the failure path, e.g. call
avformat_close_input(&avFormatContext) when avformat_find_stream_info fails (or add a
MediaInfoWorker destructor / OnError cleanup that closes avFormatContext if it is still owned by
the worker).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions