Skip to content

Fix four Support example plugins found by fuzzing - #280

Open
garyo wants to merge 4 commits into
mainfrom
fix/support-plugins-fuzzing
Open

garyo wants to merge 4 commits into
mainfrom
fix/support-plugins-fuzzing

Conversation

@garyo

@garyo garyo commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Fuzzing the plugins with a new command-line test host (not yet public) turned these up.

  • Noise renders differently in tiles. It seeded the RNG in every call to multiThreadProcessImages from the time and the first row of that call's window. Fix: hash the time-based seed, its position and the component.
  • GPUGain offered an Alpha output it can't render. Its output clip listed Alpha as well as RGBA, but its source takes only RGBA and every render path (CPU, CUDA, Metal, OpenCL) processes four floats a pixel. A host that chose Alpha would get kOfxStatErrUnsupported from the render. The output clip now supports only RGBA.
  • Gamma turned negative values into NaNs. The Gamma example in the MultiBundle plugins raised each component to its gamma with pow. It now applies the gamma to the magnitude and keeps the sign, leaving non-negative values as they were.
  • Retimer asked for frames it didn't fetch. It rendered from a source time (the integral of its speed curve, or the host's SourceTime in the retimer context), but answered GetFramesNeeded from the output time. At speed 0.14 it asked for frames 31–32 and fetched frames 4 and 5. Fixed so both now use one getSourceTime().

Assisted-by: Claude Code / Claude Opus 5.5

garyo and others added 4 commits September 24, 2026 11:34
The Noise generator seeded a Mersenne Twister in every call to
multiThreadProcessImages, from the time and the first row of that call's
window, then drew values in scan order. A pixel's noise therefore
depended on where its tile and its thread's slice of the tile began, so
a frame rendered in tiles, or on a machine with a different number of
threads, differed from the same frame rendered whole.

Each pixel's noise is now a hash of the time-based seed, its position
and the component, so it depends only on those and the noise level. The
distribution is unchanged: uniform from 0 to the noise level.

Assisted-by: Claude Code / Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gary Oberbrunner <garyo@darkstarsystems.com>
…ender

GPUGain's output clip listed Alpha as well as RGBA among its supported
components, but its source clip takes only RGBA and every render path,
CPU, CUDA, Metal and OpenCL, processes four floats a pixel. A host that
chose Alpha for the output got kOfxStatErrUnsupported from the render,
and would otherwise have hit the check that the source and output
components match.

The output clip now supports only RGBA, which is what the plugin
renders.

Assisted-by: Claude Code / Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gary Oberbrunner <garyo@darkstarsystems.com>
The Gamma example in the MultiBundle plugins raised each component to
its gamma with pow, which is NaN for a negative value and a fractional
exponent, and flips the sign for an even integer one. Float images may
hold negative values, and the other Support and Guide examples let them
through their float paths rather than clamping them, so the Gamma
example produced NaNs wherever its input went below zero.

It now applies the gamma to the magnitude and keeps the sign, which
leaves non-negative values as they were and makes the curve symmetric
about zero, as the gain examples are.

Assisted-by: Claude Code / Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gary Oberbrunner <garyo@darkstarsystems.com>
The Retimer example rendered from a source time, the integral of its
speed curve or the host's SourceTime value in the retimer context, and
fetched the source frames either side of it. Its GetFramesNeeded answer
used the output time instead, so at any speed but 1 it told the host it
needed frames it did not fetch, and fetched frames it had not asked for:
at speed 0.14 it asked for frames 31..32 and fetched frames 4 and 5.

Both now compute the source time the same way, in getSourceTime().

Assisted-by: Claude Code / Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gary Oberbrunner <garyo@darkstarsystems.com>
@garyo
garyo marked this pull request as ready for review September 24, 2026 16:10

This branch has not been deployed

No deployments
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.

1 participant