Number: 1818
Title: dot: width (43241 >= 32768) is too large.
Submitter: John
Date: Sun Nov 15 18:00:34 2009
Subsys: Dot
Version: 2.24.0
System: x86-Linux-Debian Lenny 5.0
Severity: major
Problem:
See bug #1507. It's the same issue, but here is a fix. The limit on GD/PNG dimensions is 231-1, not 215-1. The limit on the total pixels is 232-1. The formats GIF, JPG, and WBMP have limits on each dimension of 215-1 or 216-1.

Dot tends to build long rectangular graphs, where one dimension can exceed the 16-bit limit, while the other fits in a common desktop display. This means the abort in the file gvrender_gd.c is premature.

Attached is a patch. It attempts to support 31-bit dimensions for PNGs, where the total size fits in 32-bits. There are multiple code paths for PNGs due to the plethora of graphviz optional plugins. This patches the GD and Cairo code paths.
Input file: b1818.dot
Fix:
diff -Naur graphviz-2.24.0/plugin/gd/gvrender_gd.c NEW-graphviz-2.24.0/plugin/gd/gvrender_gd.c --- graphviz-2.24.0/plugin/gd/gvrender_gd.c 2009-06-02 21:10:56.000000000 -0400 +++ NEW-graphviz-2.24.0/plugin/gd/gvrender_gd.c 2009-11-15 17:52:07.000000000 -0500 @@ -46,6 +46,12 @@ extern boolean mapbool(char *); extern pointf Bezier(pointf * V, int degree, double t, pointf * Left, pointf * Right);

+/* return maximum dimensions supported by the given format. */ +static unsigned int format_max_xy (format_type t) +{ + return (t == FORMAT_PNG || t == FORMAT_GD || t==FORMAT_GD2) ? INT_MAX : 32767 ; +} + #define BEZIERSUBDIVISION 10

static void gdgen_resolve_color(GVJ_t * job, gvcolor_t * color) @@ -72,9 +78,6 @@

static int white, black, transparent, basecolor;

-#define GD_XMAX 32767 -#define GD_YMAX 32767 - static void gdgen_begin_page(GVJ_t * job) { char *bgcolor_str = NULL, *truecolor_str = NULL; @@ -102,9 +105,14 @@ fprintf(stderr, "%s: using existing GD imagen", job->common->cmdname); im = (gdImagePtr) (job->context); } else { - if (job->width >= GD_XMAX || job->height >= GD_YMAX) { - double scale = MIN((double)GD_XMAX / job->width, - (double)GD_YMAX / job->height); + fprintf(stderr,"gdgen_begin_page. GD_XYMAX=%u w=%u h=%un", GD_XYMAX, job->width, job->height); + if (job->width >= GD_XYMAX || job->height >= GD_XYMAX + || job->width >= INT_MAX - job->height ){ + double scale = MIN( + MIN((double)GD_XYMAX / job->width, + (double)GD_XYMAX / job->height), + INT_MAX/ ((double)job->width + job->height) + ); job->width *= scale; job->height *= scale; job->zoom *= scale; diff -Naur graphviz-2.24.0/plugin/pango/gvrender_pango.c NEW-graphviz-2.24.0/plugin/pango/gvrender_pango.c --- graphviz-2.24.0/plugin/pango/gvrender_pango.c 2009-06-02 21:10:57.000000000 -0400 +++ NEW-graphviz-2.24.0/plugin/pango/gvrender_pango.c 2009-11-15 17:36:22.000000000 -0500 @@ -77,8 +77,7 @@ return CAIRO_STATUS_WRITE_ERROR; }

-#define CAIRO_XMAX 32767 -#define CAIRO_YMAX 32767 +#define CAIRO_XYMAX INT_MAX

static void cairogen_begin_page(GVJ_t * job) { @@ -109,9 +108,11 @@ case FORMAT_CAIRO: case FORMAT_PNG: default: - if (job->width >= CAIRO_XMAX || job->height >= CAIRO_YMAX) { - double scale = MIN((double)CAIRO_XMAX / job->width, - (double)CAIRO_YMAX / job->height); + if (job->width >= CAIRO_XYMAX || job->height >= CAIRO_XYMAX + || job->width >= INT_MAX - job->height ){ + double scale = MIN( MIN((double)CAIRO_XYMAX / job->width, + (double)CAIRO_XYMAX / job->height), + INT_MAX/ ((double)job->width + job->height)); job->width *= scale; job->height *= scale; job->scale.x *= scale;
Owner: *
Status: *