I have a C program that uses sprintf_s. It works fine in Windows, but when I compile my code in Linux it gives this error:
sprintf_s was not declared in this scope.
Why does this happen and how can I fix it?
It's not standard, you won't find such function on Linux.
Standard function snprintf should have a similar semantics.
sprintf_s is not part of the standard C library, so it is not portable, thus you are not able to use it in Linux.
BUT you have snprintf, which is very similar and it should help you to accomplish what you want.
sprintf_s is only part of Annex K, an optional Annex to the C11 standard:
Annex K
...
K.2 Scope
This annex specifies a series of optional extensions that can be useful in the mitigation of
security vulnerabilities in programs, and comprise new functions, macros, and types
declared or defined in existing standard headers.
...
K.3.5.3.6 The sprintf_s function
Synopsis
#define __STDC_WANT_LIB_EXT1__1
#include <stdio.h>
int sprintf_s(char * restrict s, rsize_t n,
const char * restrict format, ...);
(emphasis added)
It never made it into POSIX (or Linux) (and is not missed at all, there are even arguments about its usefulness in the committee).
For better portability, use snprintf which is part of the core standard and provides all the functionality you'll need.
sprintf_s is not part of the standard C library, and you won't be able to use it in Linux.
However, snprintf is standard and should do the same task.
During a porting of my program from Windows to Linux, I wrote following implementation in my own windows.h:
inline int sprintf_s(char* buffer, size_t sizeOfBuffer, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
va_end(ap);
return result;
}
template<size_t sizeOfBuffer>
inline int sprintf_s(char (&buffer)[sizeOfBuffer], const char* format, ...)
{
va_list ap;
va_start(ap, format);
int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
va_end(ap);
return result;
}
snprintf is insecure, only sprintf_s is secure.
snprintf does not guarantee to add a final \0, leading to possible subsequent overflows.
look at https://github.com/rurban/safeclib for a proper implementation.
Related
In my current project, I am coding according to the C11 standard (building with gcc -std=c11) and needed something like strnlen (a "safe" version of strlen which returns the length of a 0-terminated string, but only up to a given maximum). So I looked it up (e.g. https://en.cppreference.com/w/c/string/byte/strlen) and it seems the C11 standard mentions such a function, but with the name strnlen_s.
Hence I went with strnlen_s, but this turned out to be undefined when including string.h. On the other hand, strnlen is defined, so my current solution is to use strnlen with a remark that the standard name seems to be strnlen_s but that this is not defined by GCC.
The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?
Note: Microsoft (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strnlen-strnlen-s) implements both functions with the distinction that strnlen_s checks if the string pointer is NULL and returns 0 in that case while strnlen has no such check.
The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?
No, it isn't portable at all. It was never part of C. It is included in POSIX, which doesn't mean much.
I would imagine the reason why the function doesn't exist in the standard, probably because it's superfluous when we already have memchr(str, '\0', max);.
strnlen_s is part of the optional bounds-checking interface in C11 annex K. This whole chapter turned out a huge fiasco and barely any compiler implements it. Microsoft has similar named functions but they are sometimes not compatible. So I would assume that all _s functions are completely non-portable.
So use neither of these, use memchr or strlen.
EDIT
In case you must implement strnlen yourself for some reason, then this is what I'd recommend:
#include <string.h>
size_t strnlength (const char* s, size_t n)
{
const char* found = memchr(s, '\0', n);
return found ? (size_t)(found-s) : n;
}
strnlen_s() is specified in Annex K of the C Standard starting at version C11. This Annex is not widely implemented and even Microsoft's implementation is not fully conformant with the specified version. The semantics are contorted especially regarding error handling. I would recommend not using it.
strnlen() is a simple function specified in POSIX.1-2008 and available on many platforms. It is easy to implement on platforms that do not provide it:
#include <string.h>
size_t strnlen(const char *s, size_t n) {
size_t i;
for (i = 0; i < n && s[i] != '\0'; i++)
continue;
return i;
}
The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?
For C, strnlen is OK as the name is not reserved. It is not part of the standard, so OK for you to add.
POSIX reserves str...(), so you might want to use another name.
strnlen_s collides with K.3.7.4.4 The strnlen_s function and has a controversial history that you might not want your code tied into. Avoid naming your function strnlen_s().
I would avoid name coalitions to common libraries with any function one adds with 2 names: the formal less-likely-to-collide-name and macro
size_t nielsen_strnlen(const char *s, size_t maxsize);
#define slength nielsen_strnlen
Or simply go directly with something less likely to collide.
size_t nstrnlen(const char *s, size_t maxsize);
Deeper: OP appears to want to use a popular function that is outside the standard C library (or current version), but might be available when code is ported to other systems. OP wants to provide a use-my-code-if-not-available function.
Careful where you tread.
I would use a macro (or a wrapper function)
#if ON_SYSTEM_WITH_strnlen
#define slength strnlen
#else
#define slength nielsen_strnlen
#endif
... and then use calls to slenth().
Problems comes up when OP's version of code is not exactly like the desired (today and tomorrow) or because it is not standard, various implementations vary - a little bit, on its implementation. To mitigate, consider a macro or function wrapper indirection.
Side issue: Parameter order and a potential new principle to the "original principles" of C.
size_t foo1(const char *s, size_t maxsize);
// arranged such that the size of an array appears before the array.
size_t foo2(size_t maxsize, const char *s);
size_t foo3(size_t maxsize, const char s[maxsize]);
string is the c++ header and string.h is the c header (at least with gcc). strlen_s (afaik) is a Microsoft extension to the C library. You right, strlen would be the more standard. You could also use memchr if you need a byte count. To #Basile's point, if you need count of characters you need something that is UTF-8 aware.
I'm using Visual Studio 2012 to compile this sample code:
#include <stdarg.h>
#include <stdio.h>
const char * __cdecl foo(const char * format, const char * requiredArgument, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
return requiredArgument;
}
int main(int, char **)
{
foo("The %s is %d pixels wide and %d pixels high.", "box", 300, 200);
return 0;
}
The debug build of the program terminates normally after printing the message "The box is 300 pixels wide and 200 pixels high.".
The release build crashes with a segmentation fault.
My interpretation for this behavior - but I may be wrong about that, please correct me if so - is that I'm incorrectly specifying a function parameter other than the last non-variadic one in va_start, the only admissible form being here va_start(args, requiredArgument) rather than va_start(args, format) as I would like to have.
In other words, I'm misusing va_start in a way that makes the whole program flow unpredictable, and so the segmentation fault is nothing but fine here.
If my assumptions are right, I have two questions now:
Why is it even required to specify the last formally declared function parameter in va_start, if choosing anything else is apparently illegal?
Why does the picky VC++ compiler not raise a warning for such an easy to detect and potentially critical pitfall?
Why is it even required to specify the last formally declared function parameter in va_start, if choosing anything else is apparently illegal?
Because that macro needs to know the address of the last argument.
Why does the picky VC++ compiler not raise a warning for such an easy to detect and potentially critical pitfall?
Because it's just not "intelligent" enough. Or its creators decided not to include this warning. Or maybe it could, but by default it's turned off and you can turn it on using some compiler flag.
I am a student of computer science and for reasons beyond my comprehension i have only been taught to code in the TURBO compiler.
But now i have realized that i should learn to code in GCC. The problem is that i dont know any of the header files and therefore i am not able to use any of the built in functions.
All the GCC tutorials i have seen are for beginners. I am at more of an intermediate state of learning and hence if any of you know of a book or a website where i can learn the details about the header files then it would be helpful.
NOTE: just to be clear-i am a linux user.
Conio.h is not the standard header file it is available only in turbo c compiler
Check out these links
http://www.gnu.org/s/hello/manual/libc/index.html
http://www.di-mgt.com.au/src/CStdLib.html
and the previous stackoverflow question List of standard header files in C and C++
http://gcc.gnu.org/onlinedocs/gcc/
http://linux.die.net/man/1/gcc
http://www.cplusplus.com/reference/clibrary/
http://en.wikipedia.org/wiki/C_standard_library
http://publications.gbdirect.co.uk/c_book/
http://www.utas.edu.au/infosys/info/documentation/C/CStdLib.html
Most of the header files used by gcc are either C C++ or POSIX compliant. Therefore you need to learn the language. printf is in stdio.h in every C compiler that is standards compliant.
There are specific linux ones but you probably dont care about those. If you ware using a linux system the 'man' command is your friend - but it tells you the header file.
man 3 printf
produces
NAME
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - formatted output conversion
SYNOPSIS
#include <stdio.h>
....
Like if you want to use printf() (for eg..), just type man printf (man stands for manual) in your terminal if Linux or in google and you'l get all the thing you need to use printf:
Synopsis
#include <stdio.h>
int printf (const char *format, ...);
int fprintf (FILE *stream, const char *format, ...);
int sprintf (char *str, const char *format, ...);
int snprintf (char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf (const char *format, va_list ap);
int vfprintf (FILE *stream, const char *format, va_list ap);
int vsprintf (char *str, const char *format, va_list ap);
int vsnprintf (char *str, size_t size, const char *format, va_list ap);
Then to use printf(), you see that you need to include stdio.h:
#include <stdio.h>
Normally you can compile without including it but it gives you warning..
Moreover use <> to include standart header files and "" to include your headers like: #include "myHeaderinMyLocalFolder.h"
If TURBO-C (which I guess you meant) is anything like TURBO-PASCAL, with it's library of console functions, there is nothing like that in standard C. And standard C is what is usedby gcc, so if you know how to use the functions in e.g. stdio.h then there is not much difference.
Consider the following test case:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
void test(char **outa, char **outb, const char* fstra, const char* fstrb, ...) {
va_list ap;
va_start(ap, fstrb);
vasprintf(&outa, fstra, ap);
vasprintf(&outb, fstrb, ap);
va_end(ap);
}
int main(void) {
char *a, *b;
test(&a, &b, "%s", " %s\n", "foo", "bar");
/* ... */
}
The intent here is that the test() function takes two format strings and a list of parameters for both of them. The first format string is supposed to 'eat' as many arguments it needs, and the remaining ones are supposed to be used for the second format string.
So, the expected result here would be foo & bar and that's what I get with glibc. But AFAICS the machine running codepad (guess some *BSD it is), gives foo & foo and my guess is that it uses va_copy() on the argument list.
I guess I'm hitting an undefined (and ugly) behavior here; so the question is: is there a way to achieve double-format-string printf() without reimplementing it from scratch? And is there a nice way to check that behavior using autoconf without using AC_RUN_IFELSE()?
I guess some quick method of scanning format-string for the number of arguments to be consumed could work here as well (+va_copy()).
When you call one of the v*printf functions, this uses va_arg which means the value of ap is indeterminate on return.
The relevant bit lies in section 7.19.6.8 The vfprintf function in C99, which references the footnote:
As the functions vfprintf, vfscanf, vprintf, vscanf, vsnprintf, vsprintf, and vsscanf invoke theva_argmacro, the value ofargafter the return is indeterminate.
This has survived to the latest draft of C1x I have as well, so I suspect it's not going to change quickly.
There is no portable way to do what you're attempting using the higher-level v*printf functions although you could resort to using the lower level stuff.
The standard is very clear in that a called function using va_arg on a va_list variable renders it indeterminate in the caller. From C99 7.15 Variable Arguments <stdarg.h>:
The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.
However, the value of ap when using va_arg on it within a single function is determinate (otherwise the whole variable arguments processing would fall apart). So you could write a single function which processed both format strings in turn, with these lower-level functions.
With the higher level stuff (as per the footnote), you are required to va_end/va_start to put the ap variable back in a determinate state and this will unfortunately reset to the start of the parameter list.
I'm not sure how much of a simplification your provided example code is but, if that's close to reality, you can acheive the same result by just combining the two format strings beforehand and using that to pass to vprintf, something like:
void test(const char* fstra, const char* fstrb, ...) {
char big_honkin_buff[1024]; // Example, don't really do this.
va_list ap;
strcpy (big_honkin_buff, fstra);
strcat (big_honkin_buff, fstrb);
va_start(ap, big_honkin_buff);
vprintf(big_honkin_buff, ap);
va_end(ap);
}
As the other answer already states, passing ap to a v*() function leaves ap in an undetermined state. So, the solution is to not depend on this state. I suggest an alternative workaround.
First, initialize ap as normal. Then determine the length of the first formatted string using vsnprintf(NULL, 0, fstra, ap). Concatenate the format strings, reinitialize ap, and split the output using the predetermined length of the first formatted string.
It should look something like the following:
void test(const char* fstra, const char* fstrb, ...) {
char *format, *buf;
char *a, *b;
int a_len, buf_len;
va_list ap;
va_start(ap, fstrb);
a_len = vsnprintf(NULL, 0, fstra, ap);
va_end(ap);
asprintf(&format, "%s%s", fstra, fstrb);
va_start(ap, fstrb);
buf_len = vasprintf(&buf, format, ap);
va_end(ap);
free(format);
a = malloc(a_len + 1);
memcpy(a, buf, a_len);
a[a_len] = '\0';
b = malloc(buf_len - a_len + 1);
memcpy(b, buf + a_len, buf_len - a_len);
b[buf_len - a_len] = '\0';
free(buf);
}
As also discussed in the other answer, this approach does not separate positional printf-style placeholders ("%1$s. I repeat, %1$s."). So the documentation for the interface should clearly state that both format strings share the same positional placeholder namespace—and that if one of the format strings uses positional placeholders then both must.
To complete the other answers, which are correct, a word about what happens in common implementations.
In 32bit Linux (and I think Windows too), passing the same ap to two functions actually works.
This is because the va_list is just a pointer to the place on the stack where the parameters are. v*rintf functions get it, but don't change it (they can't, it's passed by value).
In 64bit Linux (don't know about Windows), it doesn't work.
va_list is a struct, and v*printf gets a pointer to it (because actually it's an array of size 1 of structs). When arguments are consumed, the struct is modified. So another call to v*printf will get the parameters not from the start, but after the last one consumed.
Of course, this doesn't mean you should use a va_list twice in 32bit Linux. It's undefined behavior, which happens to work in some implementations. Don't rely on it.
I understand that the difference between the printf, fprintf, sprintf etc functions and the vprintf, vfprintf, vsprintf etc functions has to do with how they deal with the function arguments. But how specifically? Is there really any reason to use one over the other? Should I just always use printf as that is a more common thing to see in C, or is there a legitimate reason to pick vprintf instead?
printf() and friends are for normal use. vprintf() and friends are for when you want to write your own printf()-like function. Say you want to write a function to print errors:
int error(char *fmt, ...)
{
int result;
va_list args;
va_start(args, fmt);
// what here?
va_end(args);
return result;
}
You'll notice that you can't pass args to printf(), since printf() takes many arguments, rather than one va_list argument. The vprintf() functions, however, do take a va_list argument instead of a variable number of arguments, so here is the completed version:
int error(char *fmt, ...)
{
int result;
va_list args;
va_start(args, fmt);
fputs("Error: ", stderr);
result = vfprintf(stderr, fmt, args);
va_end(args);
return result;
}
You never want to use vprintf() directly, but it's incredibly handy when you need to e.g. wrap printf(). For these cases, you will define the top-level function with variable arguments (...). Then you'll collect those into a va_list, do your processing, and finally call vprintf() on the va_list to get the printout happening.
The main difficulty with variadic arguments is not that there is a variable number of arguments but that there is no name associated with each argument. The va_start, va_arg macros parse the arguments in memory (in most C compilers they are on the stack) using the type information contained in the format string cf. Kernighan and Ritchie, second edition, section 7.3.
This example shows the elegance of Python. Since C/C++ cannot reconcile the difference between int error(char *fmt, ...) and int error(char *fmt, va_list ap), thus, for every function *printf, it has to create two versions, i.e., one taking in ..., the other taking in va_list, this essentially doubles the total number of functions. In Python, you can use *list() or **dict() to pass in a va_list as ....
Hopefully, future C/C++ can support this kind of argument processing scheme.