From: Matthew Fernandez Date: Thu, 15 Dec 2022 06:15:37 +0000 (-0800) Subject: common: fix invalid use of 'memcpy' in 'printTok' X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=33c898cea516003c50c667c7f7fec77f9ae0441f;p=graphviz common: fix invalid use of 'memcpy' in 'printTok' 1349b895eca0bb04855ba46162d0ec7ba3c65010 refactored `printTok` to introduce a call to `agxbput` that passes in the return value from a previous `agxbuse` on the same buffer. This pointer still points into the destination buffer and `agxbput` bottoms out on a call to `memcpy`. So this ends up calling `memcpy` with overlapping source and destination, something that is undefined behavior in C. This change introduces a local alternative for this situation, because this is the only known place where we need to do such a thing. Gitlab: #2302, fixes #2326 --- diff --git a/lib/common/htmllex.c b/lib/common/htmllex.c index 2c8febc3f..a69e62966 100644 --- a/lib/common/htmllex.c +++ b/lib/common/htmllex.c @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -798,6 +800,15 @@ int clearHTMLlexer() #endif } +/// \p agxbput, but assume that source and destination may overlap +static UNUSED void agxbput_move(agxbuf *dst, const char *src) { + // we cannot call `agxbput` itself because it calls `memcpy`, thereby + // implicitly assuming that source and destination do not overlap + char *src_copy = gv_strdup(src); + agxbput(dst, src_copy); + free(src_copy); +} + #ifdef HAVE_EXPAT /* eatComment: * Given first character after open comment, eat characters @@ -1034,7 +1045,7 @@ static void printTok(int tok) if (tok == T_string) { const char *token_text = agxbuse(state.xb); fprintf(stderr, "%s \"%s\"\n", s, token_text); - agxbput(state.xb, token_text); + agxbput_move(state.xb, token_text); } else fprintf(stderr, "%s\n", s); }