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) {