Click here to Skip to main content
15,901,283 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In an application that I'm working on, I use dates, with size of the 'char' being declared as datestr[12], with the max length of 11 -> thru out the whole program...
While testing all possible situations, I entered a date greater than size of 11 and exited the routine, and then I get the following error: the system detected an overrun of a stack-based buffer.

1) How can I test for this oversized text entries. I currently use the
strlen() function. Is using the sizeof() function any better or what?
2) And how can you gracefully fix the issue at hand and then exit the routine gracefully without Abending and/or recieving any errors. Cause right now, the program Abends with an error message. Any ideas?? Much thanks,

What I have tried:

everything, the trial and error method, trying different avenues.
Posted

When I must use fixed-sized text buffers I make sure to use the size-limited library functions since they are much safer. Here is an example with your data :
C++
#define DATE_LENGTH 11
typedef char DateStr[ DATE_LENGTH + 1 ];   // plus one for the terminator

// a utility functions

void CopyDateStr( char * buffer, const char * datetext )
{
    strncpy( buffer, datetext, DATE_LENGTH );
}

// some random code

void RandomCode( const char * datestr )
{
   // declare a date string and initialize it
   DateStr datebuf = { 0 };
   CopyDateStr( datebuf, datestr );
   // do something else with it here
}
One key thing is to always initialize the buffer to nulls. Since strncpy is limited to DATE_LENGTH characters and an additional one was allowed for the null, the string will always be null terminated, even if it was too big for the buffer. I prefer to detect data format errors, such as excessive length, when it is first input which would be when you acquire it by prompting the user or read it from a file or database.

Other useful, size-limited functions include snprintf and strncat.
 
Share this answer
 
Comments
samtoad 29-Apr-24 18:27pm    
Rick York,
I did this, and it worked. W/o the "const int" statement, it abended.
void CopyDateStr( char * buffer, const char * datetext ) {
const int MaxDateLength = 11;
strncpy(dateout, datein, MaxDateLength);
dateout[MaxDateLength] = '\0';
return(1);
}
Thanks

The 'strncat' reminds me of the strncpy statement.
thx
k5054 29-Apr-24 18:50pm    
void functions should not return a value.
You should also avoid "magic numbers" (e.g. MaxDateLength = 11). If you change the size of dateout you then need to find everywhere that you've used the "magic" 11. See Rick's example, where the size of the string is a #define. If you need to change the size, you only need to change the value of the #define, and recompile, and no overflows/underflows.
Rick York 29-Apr-24 23:51pm    
I wrote the code the way it is specifically so I could avoid setting the null character. Initializing the buffer that way means you do not have to because it's taken care of. Using the strncpy function with the appropriate size insures that the terminating null character is not touched. THAT is why the type is defined with the +1 - it simplifies the code.
Without some code examples, it's not clear where the issue is. In particular, how are you getting your data? For example
C
char buff[10];
scanf("%s", buff);

will overflow your input buffer.

You can tell scanf how long your input buffer is though via scanf("%9s", buff). That's OK, but its then hard to tell if there's any unread data in the input buffer. Better would be to do something like
C
int valid_date(const char *);  /* a function that checks its parameter is a valid date */
                               /* has the correct length, format,not an  */
                               /* "impossible" date like 19-19-1919 */
/* ... */
char buff[1024] = "";
while( ! valid_date(buff) )
{
    printf("Enter valid date: ":
    fgets(buff, 1024, stdin);
    char *nl = strchr(buff, '\n');  /* find the newline in input buff */

    /* check for and remove any unread input */
    if( *nl == NULL )
    {
        char tmp[1024];
        do {
           fgets(tmp, 1024, stdin)
        } while( strchr(tmp, '\n') == NULL );
     }
    else {
       *nl = '\0'; /* remove newline char from buff */
    }  
}
strcpy(date, buff);  /* since we've got this far, we know we have a valid date! */
You might also want to check for something like "quit", or "today" or maybe other possible responses, and handle appropriately. The important thing is that you only read a known number of characters from your input source, so you can't get a buffer overflow, and then check that the input is valid. A malicious actor then can't then use a buffer overflow to compromise your program.

Addendum:
Thinking about it, that inner do/while loop isn't strictly necessary, since the outer loop will read the whole input buffer, anyway. But the inner loop does reduce the number of calls to valid_date(), which might be expensive. It's almost certainly more expensive than strchr() which is probably implemented in efficient assembler (eg. AVX or similar), at least for optimized builds.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900