Search code examples
c++printfvalgrind

c++ sprintf remove undefined behavior


I know, that something like this

char a[1024] = "Hello";
char b[6] = "World";

sprintf(a, "%s %s", a, b);

causes undefined behavior. I know, I could use other functions like strcat but if I want to use the sprintf function (I know the risk I could write over the array boundaries) could I remove the undefined behavior if I write something like this

sprintf(a + strlen(a), "%s %s", a, b)

or is it still undefined and I have to use a temporary variable?


Solution

  • You are right that the line

    sprintf(a, "%s %s", a, b);

    will cause undefined behavior, because the source and destination strings overlap.

    However, the line

    sprintf(a + strlen(a), "%s %s", a, b);

    would still cause undefined behavior, because a + strlen(a) is the address of the terminating null character of the string a (which means the source string a and the destination string a + strlen(a) still overlap). If the strings should not overlap, then the line must be changed to the following:

    sprintf(a + strlen(a) + 1, "%s %s", a, b);

    Since there is no longer any overlap, the line will not cause undefined behavior.

    If you want to be able to copy memory from one memory buffer to another memory buffer which overlaps the first memory buffer, then I recommend using the function memmove. In contrast to memcpy, the function memmove permits overlapping memory buffers and behaves as if the content were first written to a temporary buffer before being written to the destination buffer. Therefore, the behavior of that function is not undefined, but well-defined, even if the buffers overlap. Unfortunately, there is no equivalent function strmove for strings.