I understand snprintf will return a negative value when "an encoding error occurs"
But what is a simple example of such an "encoding error" that will produce that result?
I'm working with gcc 10.2.0 C compiler, and I've tried malformed format specifiers, unreasonably large numbers for field length, and even null format strings.
This relates to repeatedly doing something like:
length += snprintf(...
to build up a formatted string.
That might be safe if it is certain not to return a negative value.
Advancing the buffer pointer by a negative length could cause it to go out of bounds. But I'm looking for a case where that would actually happen. If there is such a case then the added complexity of this may be warranted:
length += result = snprintf(...
So far I couldn't find a scenario where it would be worth adding complexity for a check of a value that the compiler may never produce. Maybe you can give a simple example of one.
The sprintf function returns the number of characters stored in the array s , not including the terminating null character. The behavior of this function is undefined if copying takes place between objects that overlap—for example, if s is also given as an argument to be printed under control of the ' %s ' conversion.
In UNIX, it can fail: EILSEQ A wide-character code that does not correspond to a valid character has been detected. EINVAL There are insufficient arguments. EILSEQ has already been mentioned.
sprintf() function is a file handling function in C programming language which is used to write formatted output to the string.
Definition of sprintf: The sprintf function returns character objects containing a formatted combination of input values. In this tutorial, I’ll show you based on six examples how to use sprintf in the R programming language.
Note: The output of sprintf is a character string and not a numeric value as the input was. sprintf also enables the formatting of the number of digits before the decimal separator.
The sprintf R function is also used to control exponential notation in R. The following syntax returns our number as scientific notation with a lower case e… sprintf ("%e", x) # Exponential notation # "1.234560e+02" …and the following code returns an upper case E to the RStudio console:
We can now use sprintf to format the decimal places. The default number of decimal places is printed as follows (i.e. six digits after the decimal point ): We can control the number of decimal places by adding a point and a number between the percentage sign and the f. For instance, we can print ten digits after the decimal point…
What is an encoding error for sprintf that should return -1?
On my machine, "%ls"
did not like the 0xFFFF
- certainly an encoding error.
char buf[42];
wchar_t s[] = { 0xFFFF,49,50,51,0 };
int i = snprintf(buf, sizeof buf, "<%ls>", s);
printf("%d\n", i);
Output
-1
Below code returned -1, but not so much due to encoding error as for pathological format.
#include <stdio.h>
int main() {
size_t n = 0xFFFFFFFFLLu + 1;
char *fmt = malloc(n);
if (fmt == NULL) {
puts("OOM");
return -42;
}
memset(fmt, 'x', n);
fmt[n - 1] = '\0';
char buf[42];
int i = snprintf(buf, sizeof buf, fmt);
printf("%d %x\n", i, (unsigned) i);
free(fmt);
return 7;
}
Output
-1 ffffffff
I did get a surprising -1 when passing a too big a size, even though the snprintf()
only needed 6 bytes.
char buf[42];
int i = snprintf(buf, 4299195472, "Hello");
printf("%d\n", i);
Output
-1
I was able to come up with a short example returning -1 on a *fprintf()
to stdout
due to orientation conflict.
#include <wchar.h>
#include <stdio.h>
int main() {
int w = wprintf(L"Hello wide world\n");
wprintf(L"%d\n", w);
int s = printf("Hello world\n");
wprintf(L"%d\n", s);
}
Output
Hello wide world
17
-1
Normally you only expect an error from printf and family when an output error occurs. From the Linux man page:
If an output error is encountered, a negative value is returned.
So if you are outputting to a FILE and an output error of some kind (EPIPE, EIO) occurs, you'll get a negative return value. For s[n]printf, since there's no output, there would never be a negative return value.
The standard talks about the possibility of an "encoding error", but only defines what that means with respect to wide character streams, with a note that byte streams might need to convert to wide streams in some cases.
An encoding error occurs if the character sequence presented to the underlying mbrtowc function does not form a valid (generalized) multibyte character, or if the code value passed to the underlying wcrtomb does not correspond to a valid (generalized) multibyte character. The wide character input/output functions and the byte input/output functions store the value of the macro EILSEQ in errno if and only if an encoding error occurs.
That would seem to imply that you can get an encoding error if you use the %ls
or %lc
formats to convert a wide string or characters to bytes. Not sure if there are any other cases where it could occur.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With