Overlapping memory with sprintf(snprintf)

snprintf vs sprintf
what is memory overlapping
os snprintf
stdio snprintf
memcpy overlapping memory
sprintf linux
snprintf error
source and destination overlap in strcpy

Edit: What about if we had this

char value_arr[8];    
// value_arr is set to some value
snprintf(value_arr, 8, "%d", *value_arr);

is this behavior defined?


Let's say for some ungainly reason I have

char value_arr[8];
// value_arr is set to some value
int* value_i = reinterpret_cast<int*>(value_arr);

snprintf(value_arr, 8, "%d", *value_i); // the behaviour in question

Is there a guarantee that, for example, if *value_i = 7, then value_arr will take on the value of "7". Is this behavior defined? Such that value_i is first dereferenced, then passed by value, and then formatted, then stored into the array.

Normally, the value of *value_i can be expected to not change, but storing the string into value_arr violates that.

It seems to function as expected when I test it, but I can't seem to find a definitive answer in the documentation. The function signature has ..., which to my knowledge has something to do with va_list, but I'm afraid I'm not very knowledgable on the workings of variadic functions.

int sprintf (char* str, const char* format, ... );

For the original code, evaluating the expression *value_i causes undefined behaviour by violating the strict aliasing rule. It is not permitted to alias a char array as int.

For the edited code, snprintf(value_arr, 8, "%d", *value_arr);, it is fine and will format the character code of the first character in the array. Evaluation of function arguments is sequenced-before entering the function. (C++17 intro.execution/11)

Overlapping memory with sprintf(snprintf) - c++. call to sprintf or snprintf causes copying to take place between objects that overlap, the behavior is undefined. Because of the overlap, the resulting behavior is undefined. Among the standard library functions with a limitation of this kind are memcpy(), strcpy(), strcat(), sprintf(), and sscanf(). The standard says of these and several other functions: If copying takes place between objects that overlap, the behavior is undefined.

It's undefined behaviour; You use a pointer of type int* to point to an object of type char[8] with different / relaxed alignment requirements compared to int*. Dereferencing this pointer then yields UB.

c documentation: Copying overlapping memory. standard library functions with a limitation of this kind are memcpy() , strcpy() , strcat() , sprintf() , and sscanf() . The main reason is that the local system's sprintf(3) function is used to perform floating point formatting. If the local system can support %[aA], then you must have C99 already and so you must also have snprintf(3) already.

The following can be found at https://en.cppreference.com/w/cpp/io/c/fprintf:

If a call to sprintf or snprintf causes copying to take place between objects that overlap, the behavior is undefined.

I would interpret your example to fall into this case and as such it would be classified as Undefined Behaviour, according to this page.

Edit: Some more details at https://linux.die.net/man/3/snprintf:

Some programs imprudently rely on code such as the following

sprintf(buf, "%s some further text", buf);

to append text to buf. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending on the version of gcc(1) used, and the compiler options employed, calls such as the above will not produce the expected results.

If copying takes place between objects that overlap, the behaviour is undefined. On success, returns the number of characters that would have been written had  The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() are equivalent to the functions printf(), fprintf(), sprintf(), snprintf(), respectively, except that they are called with a va_list instead of a variable number of arguments.

The functions in the printf() family produce output according to a format as or vsnprintf() would cause copying to take place between objects that overlap (e.g., it may contain %n, causing the printf() call to write to memory and creating a  snprintfis essentially a function that redirects the output of printfto a buffer. This is particularly useful for avoiding repetition of a formattedstring. You can build a string once and use printf("%s", mystr)instead ofprint("%d,%s,%f,%d", x,y,z,a)every time, which gets cumbersome with actualvariable names. snprintf vs sprintf.

As we know, sprintf is often risky to use because it can overflow the buffer easily, The second snprintf() is free to trample memory. and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). The memory-writing conversion specifier % n is a common target of security exploits where format strings depend on user input and is not supported by the bounds-checked printf_s family of functions. There is a sequence point after the action of each conversion specifier; this permits storing multiple % n results in the same variable or, as an edge case, printing a string modified by an earlier % n within the same call.

printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s Dynamic memory management ​int printf( const char *restrict format, . behavior of sprintf and its variants is undefined when an argument overlaps with  In short, formatting with sprintf or snprintf resulted in a totally broken string. The same, done with the _P version works perfectly. This is nonsense for me, but maybe someone can give me a hint. Notes: 1) it's not a memory problem.

Comments
  • Probably an XY problem.
  • Probably not an XY problem, since I was pretty much asking for curiosity's sake.
  • Isn't the cast itself already a problem due to different alignment restrictions?
  • @Deduplicator If it's not correctly aligned then the result of the cast is unspecified
  • "Evaluation of function arguments is sequenced-before entering the function." To clarify, is this C++17 only?
  • @ChilliDoughnuts it's always been that way, I just used the latest standard for paragraph number reference. In earlier standards the sequencing of the arguments and postfix-expression amongst each other was less strict, but there was always a sequence point on function entry
  • @M.M Ah ok I see, and so snprintf(value_arr, 8, "%s othertext", value_arr) would then be undefined from @Karlinde's answer, yes? Since in this case it would pass the pointer value.
  • The parameters to snprintf are evaluated before the call, and as it is a %d and a *value_i, it is call-by-value; so no overlap in my opinion.