Package: graphviz Version: 2.38.0-12ubuntu2 Severity: important Dear Maintainer,
The dot tool has had random crahses for dot files with multiple digraphs, sometimes leading to glib detected malloc / free corruption. I have tested this with the Address Sanitizer and Valgrind Memcheck, and found a simple memory leak (that I fixed), and a double free of the ranks (that I also fixed), and several lost memory allocations aka leaks, that I have not managed to fix, as they are somewhat secondary. This is an Ubuntu package, but I believe the issue to be still present in the Debian package. Upstream bug tracking is tedious, so I am submitting here, instead. Thanks, Stephan -- System Information: Debian Release: stretch/sid APT prefers xenial-updates APT policy: (500, 'xenial-updates'), (500, 'xenial-security'), (500, 'xenial'), (100, 'xenial-backports') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.4.0-47-generic (SMP w/2 CPU cores) Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages graphviz depends on: ii libc6 2.23-0ubuntu4 ii libcdt5 2.38.0-12ubuntu2 ii libcgraph6 2.38.0-12ubuntu2 ii libexpat1 2.1.0-7ubuntu0.16.04.2 ii libgd3 2.1.1-4ubuntu0.16.04.5 ii libgvc6 2.38.0-12ubuntu2 ii libgvpr2 2.38.0-12ubuntu2 ii libx11-6 2:1.6.3-1ubuntu2 ii libxaw7 2:1.0.13-1 ii libxmu6 2:1.1.2-2 ii libxt6 1:1.1.5-0ubuntu1 Versions of packages graphviz recommends: ii fonts-liberation 1.07.4-1 Versions of packages graphviz suggests: pn graphviz-doc <none> ii gsfonts 1:8.11+urwcyr1.0.7~pre44-4.2ubuntu1 -- no debconf information
--- graphviz.old/graphviz-2.38.0/lib/dotgen/dotinit.c 2014-04-13 21:40:25.000000000 +0100 +++ graphviz/graphviz-2.38.0/lib/dotgen/dotinit.c 2016-11-23 19:32:53.000000000 +0000 @@ -162,6 +162,8 @@ free_list(GD_comp(g)); if (GD_rank(g)) { + // SD: The deallocates here will also deallocate the .v field which + // aliases; and were causing double free errors for (i = GD_minrank(g); i <= GD_maxrank(g); i++) free(GD_rank(g)[i].av); if (GD_minrank(g) == -1) --- graphviz.old/graphviz-2.38.0/lib/dotgen/flat.c 2014-04-13 21:40:25.000000000 +0100 +++ graphviz/graphviz-2.38.0/lib/dotgen/flat.c 2016-11-23 19:31:59.000000000 +0000 @@ -22,6 +22,11 @@ v = GD_rank(g)[r].v = ALLOC(GD_rank(g)[r].n + 2, GD_rank(g)[r].v, node_t *); + + // Keep v and av in sync; ALLOC may move the previous allocation of .v and + // they are supposed to stay in sync + GD_rank(g)[r].av = GD_rank(g)[r].v; + for (i = GD_rank(g)[r].n; i > pos; i--) { v[i] = v[i - 1]; ND_order(v[i])++; --- graphviz.old/graphviz-2.38.0/lib/dotgen/mincross.c 2014-04-13 21:40:25.000000000 +0100 +++ graphviz/graphviz-2.38.0/lib/dotgen/mincross.c 2016-11-23 19:33:41.000000000 +0000 @@ -1053,7 +1053,14 @@ GD_rank(g) = N_NEW(GD_maxrank(g) + 2, rank_t); for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { GD_rank(g)[r].an = GD_rank(g)[r].n = cn[r]; + // SD: Below allocation is unsafe, as these get deallocated differently + // + // node_t **v; /* ordered list of nodes in rank */ + // node_t **av; /* allocated list of nodes in rank */ GD_rank(g)[r].av = GD_rank(g)[r].v = N_NEW(cn[r] + 1, node_t *); + // SD: Trying to have separate allocations does not work, below + //GD_rank(g)[r].av = N_NEW(cn[r] + 1, node_t *); + //GD_rank(g)[r].v = N_NEW(cn[r] + 1, node_t *); } free(cn); } --- graphviz.old/graphviz-2.38.0/lib/gvpr/mkdefs.c 2014-04-13 21:40:25.000000000 +0100 +++ graphviz/graphviz-2.38.0/lib/gvpr/mkdefs.c 2016-11-23 10:50:27.000000000 +0000 @@ -147,6 +147,7 @@ } buf = malloc(BSIZE); } + free(buf); fp = fopen(filename, "w"); if (!fp) {