I was experimenting with Winsock2 at the moment, and got a warning that inet_ntoa() is deprecated and that I should use inet_pton(). I tried it, but it was little endian, so the whole string that was saved in the buffer was "wrong". I'm guessing inet_ntoa() is big endian?
And I could only use inet_pton() with #include <ws2tcpip.h>, so for me it just gets more confusing from here on. Why should I use something else outside the <winsock2.h> library?
Currently, I'm avoiding this by using #pragma warning(disable : 4996), which I don't like, because I just don't want to ignore all warnings.
This whole Winsock topic is like a maze for me, sorry if I'm missing some information, hope that's enough.
inet_pton() is NOT the successor for inet_ntoa(), but for inet_addr() instead. You want inet_ntop() instead.
inet_ntoa()/inet_ntop() convert an IP address from binary form to string form. inet_addr()/inet_pton() do the opposite conversion.
However, there are actually several functions that you can use instead of inet_ntoa(), including getnameinfo(), WSAAddressToString(), RtlIpv4AddressToString()/RtlIpv6AddressToString(), etc.
That being said, yes inet_ntoa() is indeed deprecated, because it only support IPv4 addresses. Functions like inet_ntop(), getnameinfo(), etc support both IPv4 and IPv6 addresses, which makes writing IP version-agnostic code a bit easier.
If you are having trouble with inet_ntop() then you are using it wrong, but you did not show your code. IPv4 addresses are always expressed in binary form in "network byte order" (big endian), even on little endian systems, like Windows.
As for <ws2tcpip.h>, that is part of the Winsock2 library. Nothing requires an API to only have 1 header file (indeed, the Win32 API as a whole consists of thousands of header files, beginning with but not limited to <windows.h>).
The correct way to deal with the deprecation warning is to update your code to use a modern API that is not deprecated, like it wants you to. Otherwise, if that is not an option for you at this time, then at the very least you can use #pragma warning(suppress : 4996) on just the affected code, rather than use #pragma warning(disable : 4996) globally. Or, you can define _WINSOCK_DEPRECATED_NO_WARNINGS in your project setup, or you can #define it in your code before #include'ing any Winsock2 headers.
inet_ntoa() has several limitations that limit its usefulness in the modern world.
For one thing, it only works for IPv4 addresses -- if you need to convert an IPv6 address into human-readable text, you're out of luck as far as inet_ntoa() is concerned.
Another problem is that inet_ntoa() returns a char * that points to a static buffer, which is problematic -- if you don't immediately copy out the string into somewhere else, the static buffer's contents might be overwritten by another sockets-API call before you read it, which could be a difficult runtime bug to track down and fix. (There might also be race-conditions possible when multiple threads are calling inet_ntoa() around the same time, although the wording of Microsoft's documentation page makes me suspect that Microsoft may be returning a pointer to a thread-local buffer to avoid that particular can of worms)
Best practice would therefore be to avoid calling inet_ntoa() if possible, and call its modern replacement inet_ntop() instead. (inet_ntop() is a bit harder to use, but it avoids the problems listed above)
Related
I'm writing a C shared library for internal use (I'll be dlopen()'ing it to a c++ application, if that matters). The shared library loads (amongst other things) some java code through a JNI module, which means all manners of nightmare error modes can come out of the JVM that I need to handle intelligently in the application. Additionally, this library needs to be re-entrant. Is there in idiom for passing error strings back in this case, or am I stuck mapping errors to integers and using printfs to debug things?
Thanks!
My approach to the problem would be a little different from everyone else's. They're not wrong, it's just that I've had to wrestle with a different aspect of this problem.
A C API needs to provide numeric error codes, so that the code using the API can take sensible measures to recover from errors when appropriate, and pass them along when not. The errno.h codes demonstrate a good categorization of errors; in fact, if you can reuse those codes (or just pass them along, e.g. if all your errors come ultimately from system calls), do so.
Do not copy errno itself. If possible, return error codes directly from functions that can fail. If that is not possible, have a GetLastError() method on your state object. You have a state object, yes?
If you have to invent your own codes (the errno.h codes don't cut it), provide a function analogous to strerror, that converts these codes to human-readable strings.
It may or may not be appropriate to translate these strings. If they're meant to be read only by developers, don't bother. But if you need to show them to the end user, then yeah, you need to translate them.
The untranslated version of these strings should indeed be just string constants, so you have no allocation headaches. However, do not waste time and effort coding your own translation infrastructure. Use GNU gettext.
If your code is layered on top of another piece of code, it is vital that you provide direct access to all the error information and relevant context information that that code produces, and you make it easy for developers against your code to wrap up all that information in an error message for the end user.
For instance, if your library produces error codes of its own devising as a direct consequence of failing system calls, your state object needs methods that return the errno value observed immediately after the system call that failed, the name of the file involved (if any), and ideally also the name of the system call itself. People get this wrong waaay too often -- for instance, SQLite, otherwise a well designed API, does not expose the errno value or the name of the file, which makes it infuriatingly hard to distinguish "the file permissions on the database are wrong" from "you have a bug in your code".
EDIT: Addendum: common mistakes in this area include:
Contorting your API (e.g. with use of out-parameters) so that functions that would naturally return some other value can return an error code.
Not exposing enough detail for callers to be able to produce an error message that allows a knowledgeable human to fix the problem. (This knowledgeable human may not be the end user. It may be that your error messages wind up in server log files or crash reports for developers' eyes only.)
Exposing too many different fine distinctions among errors. If your callers will never plausibly do different things in response to two different error codes, they should be the same code.
Providing more than one success code. This is asking for subtle bugs.
Also, think very carefully about which APIs ought to be allowed to fail. Here are some things that should never fail:
Read-only data accessors, especially those that return scalar quantities, most especially those that return Booleans.
Destructors, in the most general sense. (This is a classic mistake in the UNIX kernel API: close and munmap should not be able to fail. Thankfully, at least _exit can't.)
There is a strong case that you should immediately call abort if malloc fails rather than trying to propagate it to your caller. (This is not true in C++ thanks to exceptions and RAII -- if you are so lucky as to be working on a C++ project that uses both of those properly.)
In closing: for an example of how to do just about everything wrong, look no further than XPCOM.
You return pointers to static const char [] objects. This is always the correct way to handle error strings. If you need them localized, you return pointers to read-only memory-mapped localization strings.
In C, if you don't have internationalization (I18N) or localization (L10N) to worry about, then pointers to constant data is a good way to supply error message strings. However, you often find that the error messages need some supporting information (such as the name of the file that could not be opened), which cannot really be handled by constant data.
With I18N/L10N to worry about, I'd recommend storing the fixed message strings for each language in an appropriately formatted file, and then using mmap() to 'read' the file into memory before you fork any threads. The area so mapped should then be treated as read-only (use PROT_READ in the call to mmap()).
This avoids complicated issues of memory management and avoids memory leaks.
Consider whether to provide a function that can be called to get the latest error. It can have a prototype such as:
int get_error(int errnum, char *buffer, size_t buflen);
I'm assuming that the error number is returned by some other function call; the library function then consults any threadsafe memory it has about the current thread and the last error condition returned to that thread, and formats an appropriate error message (possibly truncated) into the given buffer.
With C++, you can return (a reference to) a standard String from the error reporting mechanism; this means you can format the string to include the file name or other dynamic attributes. The code that collects the information will be responsible for releasing the string, which isn't (shouldn't be) a problem because of the destructors that C++ has. You might still want to use mmap() to load the format strings for the messags.
You do need to be careful about the files you load and, in particular, any strings used as format strings. (Also, if you are dealing with I18N/L10N, you need to worry about whether to use the 'n$ notation to allow for argument reordering; and you have to worry about different rules for different cultures/languages about the order in which the words of a sentence are presented.)
I guess you could use PWideChars, as Windows does. Its thread safe. What you need is that the calling app creates a PwideChar that the Dll will use to set an error. Then, the callling app needs to read that PWideChar and free its memory.
R. has a good answer (use static const char []), but if you are going to have various spoken languages, I like to use an Enum to define the error codes. That is better than some #define of a bunch of names to an int value.
return integers, don't set some global variable (like errno— even if it is potentially TLSed by an implementation); aking to Linux kernel's style of return -ENOENT;.
have a function similar to strerror that takes such an integer and returns a pointer to a const string. This function can transparently do I18N if needed, too, as gettext-returnable strings also remain constant over the lifetime of the translation database.
If you need to provide non-static error messages, then I recommend returning strings like this: error_code_t function(, char** err_msg). Then provide a function to free the error message: void free_error_message(char* err_msg). This way you hide how the error strings are allocated and freed. This is of course only worth implementing of your error strings are dynamic in nature, meaning that they convey more than just a translation of error codes.
Please havy oversight with mu formatting. I'm writing this on a cell phone...
I'm porting an existing Windows application to Linux.
The most of the OS APIs\ Microsoft non-standard extension functions can be easily (more or less...) replaced by equivalent Linux\ GCC APIs, however, I don't know how to deal with sprintf_s which gets variable numbers of arguments.
Does anyone have an idea (If you can please put the code example as well) for that?
Thank you all in advance.
First, can you just port your code to use C++ iostreams instead (for example ostringstream)? This would completely remove all the possible issues with the sprintf line of functions, and if there are a limited number of call points is probably the best option.
If that isn't an option: The sprintf_s function is basically a helper to prevent mistakes (and external abuse to cause buffer overflows. From http://msdn.microsoft.com/en-us/library/ce3zzk1k%28VS.80%29.aspx we learn that it does two things: It checks the format string for valid formats (this doesn't mean it does type checking - it still can't do that), and it allows a max length to be specified.
The best replacement will be snprintf which does have limitations compared to sprintf_s. It won't do format string validation. And not all versions guarantee that the final string will be null terminated: You always want to also store a null into the last character of your buffer after the call to ensure that the final string is null terminated.
Add to end of your header file or beginning of source file:
#ifndef _WIN32
#define sprintf_s(dest,len,format,...) sprintf(dest,format,__VA_ARGS__)
#endif
snprintf has the same signature, but AFAIK it behaves in a slightly different way.
sprintf_s is just a "secure" version (takes buffer length as extra argument) of sprintf , cant you just use sprintf for your port ?
Why not just provide a conditionally compiled implementation of sprintf_s for Linux? This implementation could simply ignore the extra argument and call through to sprintf().
I'm trying to get rid of some compiler warnings that say strcpy, sprintf, etc are unsafe.
I get why they're unsafe, but I can't think of a good way to fix the code, in a C++ style.
Here's a excerpt of the code:
extList->names[i]=(char *)malloc(length*sizeof(char));
strcpy(extList->names[i],extName); // unsafe
// strncpy(extList->names[i],extName,length); // also unsafe
Here's the message:
C4996: 'strcpy': This function or variable may be
unsafe. Consider using strcpy_s instead. To disable deprecation, use
_CRT_SECURE_NO_WARNINGS. See online help for details.
I can't think of a safe way to copy the data over in C++ without knowing the length of the stuff to copy.
I know there's strlen(), but that's also unsafe since it assumes (maybe incorrectly) that the data is null-terminated.
Also:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: 'sprintf': This function or variable may be unsafe. Consider
using sprintf_s instead. To disable deprecation, use
_CRT_SECURE_NO_WARNINGS. See online help for details.
Using std::string to concatenate is easy enough, but then I need to get the data into extStr somehow (and not using strcpy, lol). The string::c_str() function returns a pointer to un-modifiable data, so I can't just set extStr equal to it. (And I'm not even sure if the c_str() pointer needs delete called on it later? Does it allocate space using "new"?)
Any advice on this stuff?
This is part of a 10,000 line file that's not mine... so I'm not exactly keen on re-writing the thing in the C++ way.
You don't really need pragmas to disable them.
For win32/msvc, in ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions, add following macros:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Or you can pass thos in command line parameters (-D_CRT_SECURE_NO_DEPRECATE). You can probably #define them at the beginning of certain *.cpp files.
Also, there are probably more of them (see crtdefs.h - looks like there are a lot of them...). Those kind of warnings normally tell you with which macros you can disable them - just read compiler output.
Here is another answer to this question.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
strcpy(destination, source);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
If getting rid of warnings only is your objective... simply define this _CRT_SECURE_NO_WARNINGS and it will suppress all the deprecation warnings. But this will not fix the underlying problems with unsafe CRT functions.
If you are on visual studio version >= 2005 and want to fix these warnings in a proper way... easiest method is to #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 and #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1 in your project.
without any further code changes you can observe most of the warnings are fixed automatically. By defining this windows will automatically call the secure overloaded functions for most of the unsafe CRT functions. Buffer sizes for static arrays are calculated automatically.
Although Dynamically allocated buffers are not fixed by this way and we need to fix them manually. Please refer this link for further details.
Below is a way to correct your example programatically
strcpy_s(extList->names[i], length, extName);
You do know how much to copy - you allocated space for it!
Surely you wouldn't willingly copy more than the space you allocated?
I would prefer to use a method that explicitly avoids buffer overruns by limiting the number of items copied. Back when I was a C programmer we used
dest = malloc(len); // note: where did we get len?
if ( dest is null ) panic! // note: malloc can fail
strncpy(dest, src, len);
dest[len-1] =0;
This is slightly messy, and has been pointed out is using strncpy() a method which really was originally designed for fixed-width fields rather than strings. However it does ach
There are methods such as strdup() and strlcpy() which may we help.
My recommendations:
1). Your target should not be to suppress warnings but to make the code robust.
2). When copying strings you need to ensure these things:
Protect yourself from bad input, for example an unterminated or excessively long string.
Protect yourself from malloc failures,
Strongly prefer copies of counted numbers of characters to copying until we see a null
If you claim to build a string, then make abolsutely sure you null terminate it
If strlcpy() is available in your environment then you could use it, otherwise why not write your own little utilityy function? Then if there are warnings in just that function you've localised then problem.
In your first example, you know the length already. Since you aren't allocating length+1 bytes I'll assume that length INCLUDES the null terminator. In that case, just std::copy the string: std::copy(extName, extName + length, expList->names[i]);
In your second example assuming the source strings are null terminated you could compute the destination string length and use std::copy again to concatenate manually, or you could use std::string and the std::copy from the results of c_str into your destination (Again assuming you allocated enough space for it).
c_str() does not allocate memory that would require external deletion.
Finally note that sizeof(char) will always be one and so is redundant in your malloc, although the number of bits in that character may not be 8 (See CHAR_BIT).
I think that you should replace all the function-calls if possible to call an implementation of your own. A good example here would be a function to replace strcpy and call the compiler-specific version of strcpy inside it. Your implementation can then easily be modified to suit any compiler of your choice, specifically if you will be adding or changing platforms/compilers.
Example:
char* StringCopy(char* Destination, const char* Source, size_t DestinationSize)
{
#ifdef _MSC_VER
return strcpy_s(Destination, Source, DestinationSize);
#else
if(!(strlen(Source) >= DestinationSize))
return strcpy(Destination, Source);
else
return 0x0;
#endif
}
If portability is not a concern, you can use 'strcpy_s'.
as it is suggested in the message, use _CRT_SECURE_NO_WARNINGS to disable this warnings.
in ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions, add following macros:
_CRT_SECURE_NO_WARNINGS
If this code is only to be compiled for windows platform then it is better to use the secured version of these functions. However, if this code is going to compiled across multiple platforms(linux, Aix etc) then either you can disable the warning in your windows project configuration file (for example, .vcxproj) by using _CRT_SECURE_NO_WARNINGS or, you can use a code snippet like this one in places where those functions have been called in the .cpp file.
#if _OS_ == _OS__WINDOWS
//secure function call
#else
//already written code
#endif
I get this warning saying that tmpnam is dangerous, but I would prefer to use it, since it can be used as is in Windows as well as Linux. I was wondering why it would be considered dangerous (I'm guessing it's because of the potential for misuse rather than it actually not working properly).
From tmpnam manpage :
The tmpnam() function generates a different string each time it is called, up to TMP_MAX times. If it is called more than TMP_MAX times, the behavior is implementation defined.
Although tmpnam() generates names that are difficult to guess, it is nevertheless possible that between the time that tmpnam() returns a pathname, and the time that the program opens it, another program might create that pathname using open(2), or create it as a symbolic link. This can lead to security holes. To avoid such possibilities, use the open(2) O_EXCL flag to open the pathname. Or better yet, use mkstemp(3) or tmpfile(3).
Mktemp really create the file, so you are assured it works, whereas tmpnam returns a name, possibly already existing.
If you want to use the same symbol on multiple platforms, use a macro to define TMPNAM. As long as you pick more secure functions with the same interface, you'll be able to use it on both. You have conditional compilation somewhere in your code anyway, right?
if you speak about the compiler warning of MSVC:
These functions are deprecated because more secure versions are available;
see tmpnam_s, _wtmpnam_s.
(http://msdn.microsoft.com/de-de/library/hs3e7355(VS.80).aspx)
otherwise just read what the manpages say about the drawbacks of this function. it is mostly about a 2nd process creating exactly the same file name as your process just did.
From the tmpnam(3) manpage:
Although tmpnam() generates names that are difficult to guess, it is nevertheless possible that between the time
that tmpnam() returns a pathname, and the time that the program opens it, another program might create that path‐
name using open(2), or create it as a symbolic link. This can lead to security holes. To avoid such possibili‐
ties, use the open(2) O_EXCL flag to open the pathname. Or better yet, use mkstemp(3) or tmpfile(3).
The function is dangerous, because you are responsible for allocating a buffer that will be big enough to handle the string that tmpnam() is going to write into that buffer. If you allocate a buffer that is too small, tmpnam() has no way of knowing that, and will overrun the buffer (Causing havoc). tmpnam_s() (MS's secure version) requires you to pass the length of the buffer, so tmpnam_s know when to stop.
I am getting warning when using the std copy function.
I have a byte array that I declare.
byte *tstArray = new byte[length];
Then I have a couple other byte arrays that are declared and initialized with some hex values that i would like to use depending on some initial user input.
I have a series of if statements that I use to basically parse out the original input, and based on some string, I choose which byte array to use and in doing so copy the results to the original tstArray.
For example:
if(substr1 == "15")
{
std::cout<<"Using byte array rated 15"<<std::endl;
std::copy(ratedArray15,ratedArray15+length,tstArray);
}
The warning i get is
warning C4996: 'std::copy': Function call with parameters
that may be unsafe
- this call relies on the caller to check that the passed
values are correct.
A possible solution is to to disable this warning is by useing -D_SCL_SECURE_NO_WARNINGS, I think. Well, that is what I am researching.
But, I am not sure if this means that my code is really unsafe and I actually needed to do some checking?
C4996 means you're using a function that was marked as __declspec(deprecated). Probably using D_SCL_SECURE_NO_WARNINGS will just #ifdef out the deprecation. You could go read the header file to know for sure.
But the question is why is it deprecated? MSDN doesn't seem to say anything about it on the std::copy() page, but I may be looking at the wrong one. Typically this was done for all "unsafe string manipulation functions" during the great security push of XPSP2. Since you aren't passing the length of your destination buffer to std::copy, if you try to write too much data to it it will happily write past the end of the buffer.
To say whether or not your usage is unsafe would require us to review your entire code. Usually there is a safer version they recommend when they deprecate a function in this manner. You could just copy the strings in some other way. This article seems to go in depth. They seem to imply you should be using a std::checked_array_iterator instead of a regular OutputIterator.
Something like:
stdext::checked_array_iterator<char *> chkd_test_array(tstArray, length);
std::copy(ratedArray15, ratedArray15+length, chkd_test_array);
(If I understand your code right.)
Basically, what this warning tells you is that you have to be absolutely sure that tstArray points to an array that is large enough to hold "length" elements, as std::copy does not check that.
Well, I assume Microsoft's unilateral deprecation of the stdlib also includes passing char* to std::copy. (They've messed with a whole range of functions actually.)
I suppose parts of it has some merit (fopen() touches global ERRNO, so it's not thread-safe) but other decisions do not seem very rational. (I'd say they took a too big swathe at the whole thing. There should be levels, such as non-threadsafe, non-checkable, etc)
I'd recommend reading the MS-doc on each function if you want to know the issues about each case though, it's pretty well documented why each function has that warning, and the cause is usually different in each case.
At least it seems that VC++ 2010 RC does not emit that warning at the default warning level.