From: John Darrington Date: Sat, 11 Jul 2020 07:35:29 +0000 (+0200) Subject: src/output/cairo-chart.h (xrchart_write_scale): Check the range and deal with the... X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f998d65fb573c1b4c12f917cc3dd0639808cfa3;p=pspp src/output/cairo-chart.h (xrchart_write_scale): Check the range and deal with the consequences. If a chart was requested where either scale had an range of zero (the minimum value and the maximum value were equal), then all sorts of memory errors could occur later in the chart's rendering. This change checks for this condition early and refuses to draw the chart in this case. --- diff --git a/src/output/cairo-chart.c b/src/output/cairo-chart.c index c5bffcd761..00eb98f5f9 100644 --- a/src/output/cairo-chart.c +++ b/src/output/cairo-chart.c @@ -1,5 +1,6 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2009, 2010, 2011, 2014, 2015 Free Software Foundation, Inc. + Copyright (C) 2004, 2009, 2010, 2011, 2014, 2015, + 2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -365,7 +366,7 @@ xrchart_text_extents (cairo_t *cr, const struct xrchart_geometry *geom, pango_font_description_free (desc); } -static void +static bool xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom, double smin, double smax, enum tick_orientation orient) { @@ -379,6 +380,9 @@ xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom, char *tick_format_string; bool tickoversize = false; + if (smax == smin) + return false; + chart_get_scale (smax, smin, &lower, &interval, &ticks); tick_format_string = chart_get_ticks_format (lower, interval, ticks, &tickscale); @@ -417,22 +421,24 @@ xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom, pos += interval; } free(tick_format_string); + + return true; } /* Set the scale for the ordinate */ -void +bool xrchart_write_yscale (cairo_t *cr, struct xrchart_geometry *geom, double smin, double smax) { - xrchart_write_scale (cr, geom, smin, smax, SCALE_ORDINATE); + return xrchart_write_scale (cr, geom, smin, smax, SCALE_ORDINATE); } /* Set the scale for the abscissa */ -void +bool xrchart_write_xscale (cairo_t *cr, struct xrchart_geometry *geom, double smin, double smax) { - xrchart_write_scale (cr, geom, smin, smax, SCALE_ABSCISSA); + return xrchart_write_scale (cr, geom, smin, smax, SCALE_ABSCISSA); } diff --git a/src/output/cairo-chart.h b/src/output/cairo-chart.h index 60ef282928..68f2978283 100644 --- a/src/output/cairo-chart.h +++ b/src/output/cairo-chart.h @@ -117,13 +117,12 @@ void xrchart_write_title (cairo_t *, const struct xrchart_geometry *, PRINTF_FORMAT (3, 4); /* Set the scale for the abscissa */ -void xrchart_write_xscale (cairo_t *, struct xrchart_geometry *, - double min, double max); - +bool xrchart_write_xscale (cairo_t *, struct xrchart_geometry *, + double min, double max) WARN_UNUSED_RESULT; /* Set the scale for the ordinate */ -void xrchart_write_yscale (cairo_t *, struct xrchart_geometry *, - double smin, double smax); +bool xrchart_write_yscale (cairo_t *, struct xrchart_geometry *, + double smin, double smax) WARN_UNUSED_RESULT; void xrchart_write_xlabel (cairo_t *, const struct xrchart_geometry *, const char *label) ; diff --git a/src/output/charts/barchart-cairo.c b/src/output/charts/barchart-cairo.c index e6f33ad118..00b33fc6b0 100644 --- a/src/output/charts/barchart-cairo.c +++ b/src/output/charts/barchart-cairo.c @@ -67,10 +67,9 @@ xrchart_draw_barchart (const struct chart_item *chart_item, cairo_t *cr, xrchart_write_ylabel (cr, geom, bc->ylabel); xrchart_write_xlabel (cr, geom, chart_item_get_title (chart_item)); - if (bc->percent) - xrchart_write_yscale (cr, geom, 0, bc->largest * 100.0 / bc->total_count); - else - xrchart_write_yscale (cr, geom, 0, bc->largest); + if (! xrchart_write_yscale (cr, geom, 0, + bc->percent ? bc->largest * 100.0 / bc->total_count : bc->largest)) + return; const double abscale = geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min; const double width = abscale / (double) (bc->n_nzcats + bc->n_pcats); diff --git a/src/output/charts/boxplot-cairo.c b/src/output/charts/boxplot-cairo.c index 041b4fabb8..b79b45f5e8 100644 --- a/src/output/charts/boxplot-cairo.c +++ b/src/output/charts/boxplot-cairo.c @@ -152,7 +152,9 @@ xrchart_draw_boxplot (const struct chart_item *chart_item, cairo_t *cr, double box_width; size_t i; - xrchart_write_yscale (cr, geom, boxplot->y_min, boxplot->y_max); + if (! xrchart_write_yscale (cr, geom, boxplot->y_min, boxplot->y_max)) + return; + xrchart_write_title (cr, geom, "%s", chart_item->title); box_width = (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / boxplot->n_boxes / 2.0; diff --git a/src/output/charts/np-plot-cairo.c b/src/output/charts/np-plot-cairo.c index e9a1e07033..aa7d677348 100644 --- a/src/output/charts/np-plot-cairo.c +++ b/src/output/charts/np-plot-cairo.c @@ -37,10 +37,13 @@ np_plot_chart_draw (const struct chart_item *chart_item, cairo_t *cr, xrchart_write_title (cr, geom, _("Normal Q-Q Plot of %s"), chart_item->title); xrchart_write_xlabel (cr, geom, _("Observed Value")); xrchart_write_ylabel (cr, geom, _("Expected Normal")); - xrchart_write_xscale (cr, geom, + if (! xrchart_write_xscale (cr, geom, npp->x_lower - npp->slack, - npp->x_upper + npp->slack); - xrchart_write_yscale (cr, geom, npp->y_first, npp->y_last); + npp->x_upper + npp->slack)) + return; + + if (! xrchart_write_yscale (cr, geom, npp->y_first, npp->y_last)) + return; data = casereader_clone (npp->data); for (; (c = casereader_read (data)) != NULL; case_unref (c)) @@ -64,8 +67,10 @@ dnp_plot_chart_draw (const struct chart_item *chart_item, cairo_t *cr, xrchart_write_title (cr, geom, _("Detrended Normal Q-Q Plot of %s"), chart_item->title); xrchart_write_xlabel (cr, geom, _("Observed Value")); xrchart_write_ylabel (cr, geom, _("Dev from Normal")); - xrchart_write_xscale (cr, geom, dnpp->y_min, dnpp->y_max); - xrchart_write_yscale (cr, geom, dnpp->dns_min, dnpp->dns_max); + if (! xrchart_write_xscale (cr, geom, dnpp->y_min, dnpp->y_max)) + return; + if (! xrchart_write_yscale (cr, geom, dnpp->dns_min, dnpp->dns_max)) + return; data = casereader_clone (dnpp->data); for (; (c = casereader_read (data)) != NULL; case_unref (c)) diff --git a/src/output/charts/plot-hist-cairo.c b/src/output/charts/plot-hist-cairo.c index 000695f331..620fe68c23 100644 --- a/src/output/charts/plot-hist-cairo.c +++ b/src/output/charts/plot-hist-cairo.c @@ -118,9 +118,11 @@ xrchart_draw_histogram (const struct chart_item *chart_item, cairo_t *cr, return; } - xrchart_write_yscale (cr, geom, 0, gsl_histogram_max_val (h->gsl_hist)); - xrchart_write_xscale (cr, geom, gsl_histogram_min (h->gsl_hist), - gsl_histogram_max (h->gsl_hist)); + if (! xrchart_write_yscale (cr, geom, 0, gsl_histogram_max_val (h->gsl_hist))) + return; + if (! xrchart_write_xscale (cr, geom, gsl_histogram_min (h->gsl_hist), + gsl_histogram_max (h->gsl_hist))) + return; /* Draw the ticks and compute if the rendered tick text is wider than the bin */ diff --git a/src/output/charts/roc-chart-cairo.c b/src/output/charts/roc-chart-cairo.c index 97f7a45d9a..ae2db62efb 100644 --- a/src/output/charts/roc-chart-cairo.c +++ b/src/output/charts/roc-chart-cairo.c @@ -37,8 +37,10 @@ xrchart_draw_roc (const struct chart_item *chart_item, cairo_t *cr, xrchart_write_xlabel (cr, geom, _("1 - Specificity")); xrchart_write_ylabel (cr, geom, _("Sensitivity")); - xrchart_write_xscale (cr, geom, 0, 1); - xrchart_write_yscale (cr, geom, 0, 1); + if (! xrchart_write_xscale (cr, geom, 0, 1)) + return; + if (! xrchart_write_yscale (cr, geom, 0, 1)) + return; if (rc->reference) { diff --git a/src/output/charts/scatterplot-cairo.c b/src/output/charts/scatterplot-cairo.c index 86e54c6e5a..cf62539fab 100644 --- a/src/output/charts/scatterplot-cairo.c +++ b/src/output/charts/scatterplot-cairo.c @@ -50,8 +50,10 @@ xrchart_draw_scatterplot (const struct chart_item *chart_item, cairo_t *cr, if (spc->byvar) byvar_width = var_get_width (spc->byvar); - xrchart_write_xscale (cr, geom, spc->x_min, spc->x_max); - xrchart_write_yscale (cr, geom, spc->y_min, spc->y_max); + if (! xrchart_write_xscale (cr, geom, spc->x_min, spc->x_max)) + return; + if (! xrchart_write_yscale (cr, geom, spc->y_min, spc->y_max)) + return; xrchart_write_title (cr, geom, _("Scatterplot %s"), chart_item->title); xrchart_write_xlabel (cr, geom, spc->xlabel); xrchart_write_ylabel (cr, geom, spc->ylabel); diff --git a/src/output/charts/scree-cairo.c b/src/output/charts/scree-cairo.c index a3ae10cd62..d203b62eff 100644 --- a/src/output/charts/scree-cairo.c +++ b/src/output/charts/scree-cairo.c @@ -44,8 +44,10 @@ xrchart_draw_scree (const struct chart_item *chart_item, cairo_t *cr, else max = fabs (min); - xrchart_write_yscale (cr, geom, 0, max); - xrchart_write_xscale (cr, geom, 0, rc->eval->size + 1); + if (! xrchart_write_yscale (cr, geom, 0, max)) + return; + if (! xrchart_write_xscale (cr, geom, 0, rc->eval->size + 1)) + return; xrchart_vector_start (cr, geom, ""); for (i = 0 ; i < rc->eval->size; ++i) diff --git a/src/output/charts/spreadlevel-cairo.c b/src/output/charts/spreadlevel-cairo.c index 389a487b01..7167c4c8e6 100644 --- a/src/output/charts/spreadlevel-cairo.c +++ b/src/output/charts/spreadlevel-cairo.c @@ -39,8 +39,11 @@ xrchart_draw_spreadlevel (const struct chart_item *chart_item, cairo_t *cr, xrchart_write_ylabel (cr, geom, _("Spread")); - xrchart_write_xscale (cr, geom, sl->x_lower, sl->x_upper); - xrchart_write_yscale (cr, geom, sl->y_lower, sl->y_upper); + if (! xrchart_write_xscale (cr, geom, sl->x_lower, sl->x_upper)) + return; + + if (! xrchart_write_yscale (cr, geom, sl->y_lower, sl->y_upper)) + return; for (i = 0 ; i < sl->n_data; ++i) {