When constructing a path, the `beginpath` and `endpath` functions assumed they
could follow a chain of `.to_orig` back pointers to eventually reach a normal
edge. However this is not necessarily true, a situation exemplified by
tests/graphs/b15.gv that caused these traversal loops to eventually reach the
start of this linked list and then dereference a null pointer.
The fix in this commit is to simply treat the head of the list as the original
edge if we have not encountered a normal edge before then. Whether this is
correct or not seems unimportant, as a graph that causes this scenario is
incorrect. This change turns a crash during path construction into a graceful
exit later when the lack of normal edges is discovered.
This fix has similarities with
84e468e775e1d1b293624f1c8e70c226eb4a6e41. Perhaps
the code base should be audited for all such traversal loops, which seem to have
been written prior to a time when constructing a non-normal-edge-containing list
became possible.
Gitlab: fixes #827
- Segmentation Fault with splines="ortho". #1658
- Transparent Label appear in SVG output #146
- Binary tcl modules should compile with -module #1285
+- b15.gv crashes dot #827
## [4.0.0] – 2022-05-29
endp->boxn = 1;
++P->start.p.x;
}
- for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
+ for (orig = e; ED_to_orig(orig) != NULL && ED_edge_type(orig) != NORMAL;
+ orig = ED_to_orig(orig));
if (n == agtail(orig))
ED_tail_port(orig).clip = false;
else
endp->boxn = 1;
++P->start.p.x;
}
- for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
+ for (orig = e; ED_to_orig(orig) != NULL && ED_edge_type(orig) != NORMAL;
+ orig = ED_to_orig(orig));
if (n == agtail(orig))
ED_tail_port(orig).clip = false;
else
endp->boxn = 1;
++P->end.p.x;
}
- for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
+ for (orig = e; ED_to_orig(orig) != NULL && ED_edge_type(orig) != NORMAL;
+ orig = ED_to_orig(orig));
if (n == aghead(orig))
ED_head_port(orig).clip = false;
else
endp->boxn = 1;
++P->end.p.x;
}
- for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
+ for (orig = e; ED_to_orig(orig) != NULL && ED_edge_type(orig) != NORMAL;
+ orig = ED_to_orig(orig));
if (n == aghead(orig))
ED_head_port(orig).clip = false;
else
# the escape sequences should have been preserved
assert "& &" in output
-@pytest.mark.xfail()
def test_827():
"""
Graphviz should not crash when processing the b15.gv example