Ticket #271 (closed defect: fixed)

Opened 3 months ago

Last modified 3 months ago

Broken isinf on Solaris 9

Reported by: human Owned by: oetiker
Priority: blocker Milestone:
Component: rrd_graph Version: 1.4.3
Keywords: Cc: dam@…

Description

The current implementation of isinf on Solaris 9 leads to the problem that valid line numbers are rejected as "out of range" as outlined in this bug reported for Orca:

The error message is

  LINE width '1:average1#0000ff:Zero-fill-on-demand' is out of range in line 'LINE1:average1#0000ff:Zero-fill-on-demand'

The code leading to this message is from rrd_graph_helper.c:

    case GF_LINE:
        if (c1 == ':') {
            gdp->linewidth = 1;
            dprintf("- using default width of 1\n");
        } else {
            i = 0;
            sscanf(&line[*eaten], "%lf:%n", &gdp->linewidth, &i);
fprintf(stderr,"LF: %lf\n", gdp->linewidth);
fprintf(stderr,"I: %ld %ld %ld\n",fpclass(gdp->linewidth),FP_SNAN,FP_QNAN);
            if (!i) {
                rrd_set_error("Cannot parse line width '%s' in line '%s'\n",
                              &line[*eaten], line);
                return 1;
            } else {
                dprintf("- scanned width %f\n", gdp->linewidth);
                if (isnan(gdp->linewidth)) {
                    rrd_set_error
                        ("LINE width '%s' is not a number in line '%s'\n",
                         &line[*eaten], line);
                    return 1;
                }
                if (isinf(gdp->linewidth)) {
                    rrd_set_error
                        ("LINE width '%s' is out of range in line '%s'\n",
                         &line[*eaten], line);
                    return 1;
                }
                if (gdp->linewidth < 0) {
                    rrd_set_error
...

The problem is the broken implementation of 'isinf' for Solaris 9 in rrd_config_bottom.h:

/* for Solaris */
#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
#  define HAVE_ISINF 1
#  ifdef isinf
#  undef isinf
#  endif
#  define isinf(a) (!!(fpclass(a) & (FP_SNAN|FP_QNAN)))
#endif

The problem is that fpclass(a) does not return a bitmask, but a number indicating the class of the floatingpoint number as documented in fpclass(3c):

     The fpclass() function returns one of the following  classes
     to which dsrc belongs:

These are from /usr/include/ieeefp.h and valid results:

typedef enum    fpclass_t {
        FP_SNAN = 0,    /* signaling NaN */
        FP_QNAN = 1,    /* quiet NaN */
        FP_NINF = 2,    /* negative infinity */
        FP_PINF = 3,    /* positive infinity */
        FP_NDENORM = 4, /* negative denormalized non-zero */
        FP_PDENORM = 5, /* positive denormalized non-zero */
        FP_NZERO = 6,   /* -0.0 */
        FP_PZERO = 7,   /* +0.0 */
        FP_NNORM = 8,   /* negative normalized non-zero */
        FP_PNORM = 9    /* positive normalized non-zero */
} fpclass_t;

This alternative implementation for isinf solves the problem:

#define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)

Change History

Changed 3 months ago by oetiker

  • status changed from new to closed
  • resolution set to fixed

indeed ... bad bug ... a regression introduced by a bad optimization added r1904 ... fixed in r2093 ... thanks

Note: See TracTickets for help on using tickets.

NOTE: The content of this website is accessible with any browser. The graphical design though relies completely on CSS2 styles. If you see this text, this means that your browser does not support CSS2. Consider upgrading to a standard conformant browser like Mozilla Firefox or Opera but also Apple's Safari or KDE's Konqueror for example. It may also be that you are looking at a mirror page which did not copy the CSS for this page. Or if some pictu res are missing, then the mirror may not have picked up the contents of the inc directory.