Skip to content

restore the volatility banner on --help and missing-plugin invocations (#1979)#1983

Open
ChrisJr404 wants to merge 1 commit intovolatilityfoundation:developfrom
ChrisJr404:restore-banner-on-help
Open

restore the volatility banner on --help and missing-plugin invocations (#1979)#1983
ChrisJr404 wants to merge 1 commit intovolatilityfoundation:developfrom
ChrisJr404:restore-banner-on-help

Conversation

@ChrisJr404
Copy link
Copy Markdown

Closes #1979.

Background

Per @eve-mem's bisection in the issue thread, commit 8479fa1 (PR #1861, "moved renderer parsing to after the plugins are imported") moved the banner-print block from before parse_args() to after it:

$ git checkout 8479fa1c
$ python vol.py --help | head
usage: vol.py [-h] [-c CONFIG] [--parallelism [{processes,threads,off}]]
              ...

Since argparse.parse_args() exits when handed --help / -h, and now exits with an error when the PLUGIN positional is missing, both common informational invocations skip the banner entirely.

Constraint @ikelos called out

Banner output depends on knowing whether it should be displayed or not (which renderer)
Knowing which renderer depends on the renderer list
Filling the renderer list depends on the plugin path
Getting the plugin path depends on having parsed the argument partially

Change

Move just the banner write block back to between the renderer-arg registration and the subparser registration:

parser.add_argument("-r", "--renderer", ..., choices=list(renderers))

# Display the banner BEFORE the subparser is added (so parse_known_args
# below treats unknown positionals as leftover instead of rejecting them
# against the PLUGIN choice list) and BEFORE parser.parse_args() runs at
# the bottom of this method (so the banner still appears when the user
# passes --help / -h, which causes argparse to print help and exit).
banner_partial_args, _ = parser.parse_known_args(known_args)
banner_output = sys.stdout
if renderers[banner_partial_args.renderer].structured_output:
    banner_output = sys.stderr
banner_output.write(f"Volatility 3 Framework {constants.PACKAGE_VERSION}\n")
banner_output.flush()

subparser = parser.add_subparsers(...)

At this point in run():

  • the plugin path has already been applied (line ~283), so plugin auto-discovery and the renderer list are populated
  • the renderer (-r) argument has been added, so the partial-parse picks up an explicit -r JSON etc.
  • the PLUGIN subparser positional has NOT been added yet, so parse_known_args doesn't reject vol.py (or any unknown plugin name) — it falls into the discarded leftover slot exactly the way the existing partial-parse at line 257 relies on

The trailing parser.parse_args() is unchanged and still does final argument validation + --help rendering; the banner just precedes its output now.

Verification

$ python3 vol.py | head -3
Volatility 3 Framework 2.28.1
usage: vol.py [-h] [-c CONFIG] [--parallelism [{processes,threads,off}]]
              ...

$ python3 vol.py --help | head -3
Volatility 3 Framework 2.28.1
usage: vol.py [-h] [-c CONFIG] [--parallelism [{processes,threads,off}]]
              ...

$ python3 vol.py -r JSON | head -3   # JSON has structured_output=True
usage: vol.py [-h] [-c CONFIG] [--parallelism [{processes,threads,off}]]
              ...
$ python3 vol.py -r JSON 2>&1 1>/dev/null | head -1
Volatility 3 Framework 2.28.1                # banner correctly redirected to stderr

flush() is added because argparse.exit() doesn't flush stdout before terminating, which would lose the banner under python3 -u-less runs.

Diff is +12 / -0 lines, single file, no public-API change.

volatilityfoundation#1979)

Commit 8479fa1 moved the renderer/plugin discovery (and with it, the
banner-print block) to after parser.parse_args(). That means

    $ vol.py --help
    $ vol.py            # missing PLUGIN argument

both exit through argparse before the banner is reached.

Move just the banner write back above the subparser registration: at
that point the renderer (`-r`) argument has been added but the PLUGIN
positional has not, so parse_known_args(...) tolerates an empty / help
/ unknown-plugin invocation and we can pick the right output stream
(stdout for the default `quick` renderer, stderr for structured
renderers like JSON / parquet so they don't pollute pipeable output).

Closes volatilityfoundation#1979.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vol.py doesn't output the volatility banner/version for --help or other argparse results.

1 participant