LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How does the return value of sprintf() work in release mode?

 
Take a look at this code.   Everything does I think it should in debug mode.  I get a popup that tells me I did a bad thing and sprintf returns a -1.  In release mode it seems I do not get the -1 returned.   What gives?
 
////////////////
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[])
{
 char string1[10];
 char string2[100];
 int  result = 0;
 
 if (InitCVIRTE (0, argv, 0) == 0)
  return -1;    /* out of memory */
 
 sprintf( string2, "xxxxxxxx string2 starts with x\n\n" );
 
 result = sprintf( string1, "hello\n\n" );
 if(result < 0 )
 {
  printf( "failed to format hello message\n");
 }
 else
 {
  printf(string1);
 }
 
 // This function returns an error as it should in debug mode
 // It seems to me that this function does NOT return an error in release mode
 result = sprintf( string1, "This is a longer message\n\n" );
 if(result < 0 )
 {
  printf( "failed to format longer message\n");
 }
 else
 {
  printf(string1);
  printf(string2);
 }
 
  Delay(20);
 
 return 0;
}
////////////////
0 Kudos
Message 1 of 9
(6,682 Views)
this behavior seems normal to me.

when running in debug mode, CVI holds informations about the type of variables and performs a lot of validity and sanity checks. this include checking for array bounds. this is why it gives an error when trying to write passed the end of string2.

when the same program is compiled in release mode, all those checls are removed for obvious performance reasons. that's why it does not detect the buffer overflow when writing to string2.

remember: in C, an array is just stored as a pointer to the first element. the language does not define any mean for storing/retrieving the length of the array nor any other type 'attributes' alike. if it was, you would be able to retrieve the size of any array at any moment using the sizeof() operator, but it is not the case. if this is a problem to you, use another language.
0 Kudos
Message 2 of 9
(6,671 Views)
i forgot to say: if you are interrested in preventing sprintf() to overflow the buffer, then you might want to use snprintf(), although i am not sure if this function is provided with NI implementation of the C runtime.
0 Kudos
Message 3 of 9
(6,651 Views)
Hey John,

The debug and release mode do run different as you have noticed and dummy_decoy explained.  CVI does not have the C implementation of the snprintf() function, but you can still perform error checking without it.  I ran your code in debug and result was set to -1 when the buffer was overwritten; when I ran your code in release mode, result was set to 26, which is greater than your buffer size.  You can use this information to determine if there was a buffer overflow.  For example you could change your code as follows:

//ARRAY_LEN could also be a const unsigned char (int)
#define ARRAY_LEN 10
...
char string2[ARRAY_LEN];
...
if(result < 0 || result >= ARRAY_LEN) 
//You still need to write a NULL at the end of the string; therefore you need result to be 1 less than ARRAY_LEN


I hope this helps!
Best Regards,
Software Engineer
Jett R
0 Kudos
Message 4 of 9
(6,621 Views)
sorry for correcting you JettR, but your code is wrong: it does not prevent the buffer overflow at all. the overflowing content of the buffer will overwrite the content of any variable which happen to be stored right after the end of the buffer... if it is a value, it will change its value, if it is a pointer it will lead to catastrophic failures.

0 Kudos
Message 5 of 9
(6,608 Views)
Hey dummy_decoy,

I think there was some confusion about my last post.  I did not claim that my code would prevent a buffer overflow; the code will only detect if an overflow has occurred.  One of the best options to prevent overflow in run mode is to ensure that your string buffer is large enough for the worst case scenario string you want to write.  You could also make a custom function that would only write a limited number of characters.  You are very right about buffer overflows being a potentially huge problem; you definitely want to avoid them at all costs.  Have a great day!

Best Regards,
Software Engineer
Jett R
0 Kudos
Message 6 of 9
(6,595 Views)

Got it.  Thanks.  This is kinda what I was thinking.

I am a bit nervous that a function behaves one way in release and another in debug and the documentation (function panel) does not alert me to this.  Makes me wonder if I have projects released that are not doing what I think they are. 

Is this issue common?  Are there other functions out there that do this?   How would I know?

Thanks

0 Kudos
Message 7 of 9
(6,565 Views)
Hey John,

This function along with other ansi C functions act differently in Release mode and Debug mode because of the different User Protection options CVI has.  You can choose to disable these option in debug mode and find out more about them in the CVI help.  You can find the topic under Programmer Reference » LabWindows/CVI Compiler Overview » User Protection.  You can also find options in the Options » Build Options dialog.  I hope this helps.
Best Regards,
Software Engineer
Jett R
0 Kudos
Message 8 of 9
(6,555 Views)

Hi John,

I also want to add to what Jett already wrote that, as far as the documentation is concerned, the return value that you are getting in the release build is the correct return value. The function should return the number of bytes of written. However, in debug mode the user protection is preventing the copying from taking place, and as such it wouldn't make sense to return the number of bytes written, since no byte was actually written.

This is analogous to calling some library function that creates an object handle. Normally, that function would return the handle of the object. But if there's some error in the parameters passed to the function that is caught by the user protection, the function will not create the object at all, and the return value cannot be the object handle. So it must return something else.

This doesn't mean that errors can't also be returned in release mode. Just not the memory-type errors that the C language normally does not catch. Those types of errors are only detected by the user protection feature of debug builds. But other errors can be detected in release builds as well.

Luis

0 Kudos
Message 9 of 9
(6,547 Views)