Package: swh-plugins
Version: 0.4.15+1-6+fh1
Severity: normal
Tags: upstream patch

The analogueOsc plugin produces NaN under some conditions.

The attached test program (linking directly to the plugin for
simplicity, but it's the same when loading it dynamically), running
on amd64, shows the bug:

% gcc osc-test.c /usr/lib/ladspa/analogue_osc_1416.so -Wl,-R/usr/lib/ladspa && 
./a.out
NaN 45602

The bug is due to a 0.0/0.0 division. Ironically, the code checks
for "the case where x ~= q", but misses the case where x == q
exactly, since nan, unlike inf, is not greater than anything.
Of course, according to Murphy's law, FP numbers are never equal,
unless you want them to be unequal. ;)

I had used the plugin for years on x86 and never seen this problem.
The difference might be due to the extended precision of the x87 vs.
XMM registers.

The attached patch fixes this particular problem. I'm not sure if
checking isnan() is really the best solution, but it's least
invasive and won't break anything else.
#include <stdio.h>
#include <ladspa.h>

int main ()
{
  int n;
  const LADSPA_Descriptor *d = ladspa_descriptor (0);
  LADSPA_Handle h = d->instantiate (d, 44100);
  LADSPA_Data w = 2, f = 440, a = 0.2, i = 0.2, b[512];
  d->connect_port (h, 0, &w);
  d->connect_port (h, 1, &f);
  d->connect_port (h, 2, &a);
  d->connect_port (h, 3, &i);
  d->connect_port (h, 4, b);
  if (d->activate)
    d->activate (h);
  for (n = 0; n < 50000; n++)
    {
      d->run (h, 512);
      if (isnan (b[0]))
        {
          printf ("NaN %i\n", n);
          return 1;
        }
    }
  printf ("OK\n");
}
--- analogue_osc_1416.xml	2009-07-28 23:18:16.000000000 +0400
+++ analogue_osc_1416.xml	2015-03-31 17:02:57.345738899 +0300
@@ -62,7 +62,7 @@
 	y = (x - q) / (1.0f - f_exp(-1.2f * (x - q))) +
               q / (1.0f - f_exp(1.2f * q));
 	/* Catch the case where x ~= q */
-	if (fabs(y) > 1.0f) {
+	if (isnan(y) || fabs(y) > 1.0f) {
 		y = 0.83333f + q / (1.0f - f_exp(1.2f * q));
 	}
 	otm2 = otm1;

Reply via email to