c - Avoiding strcpy overflow destination warning - Stack Overflow

admin2025-04-20  0

With a structure such as the following

typedef struct
{
  size_t StringLength;
  char   String[1];
} mySTRING;

and use of this structure along these lines

mySTRING * CreateString(char * Input)
{
  size_t     Len     = strlen(Input);
  int        Needed  = sizeof(mySTRING) + Len;
  mySTRING * pString = malloc(Needed);
  :
  strcpy(pString->String, Input); 
}

results, on Red Hat Linux cc compiler, in the following warning, which is fair enough.

strings.c:59:3: warning: âstrcpyâ writing 14 bytes into a region of size 1 overflows the destination [-Wstringop-overflow=]
   strcpy(pString->String, Input);

I know that, in this instance of code, this warning is something I don't need to correct. How can I tell the compiler this without turning off these warnings which might usefully find something, somewhere else, in the future.

What changes can I make to the code to show the compiler this one is OK.

With a structure such as the following

typedef struct
{
  size_t StringLength;
  char   String[1];
} mySTRING;

and use of this structure along these lines

mySTRING * CreateString(char * Input)
{
  size_t     Len     = strlen(Input);
  int        Needed  = sizeof(mySTRING) + Len;
  mySTRING * pString = malloc(Needed);
  :
  strcpy(pString->String, Input); 
}

results, on Red Hat Linux cc compiler, in the following warning, which is fair enough.

strings.c:59:3: warning: âstrcpyâ writing 14 bytes into a region of size 1 overflows the destination [-Wstringop-overflow=]
   strcpy(pString->String, Input);

I know that, in this instance of code, this warning is something I don't need to correct. How can I tell the compiler this without turning off these warnings which might usefully find something, somewhere else, in the future.

What changes can I make to the code to show the compiler this one is OK.

Share Improve this question edited Mar 4 at 12:21 Morag Hughson asked Mar 2 at 22:56 Morag HughsonMorag Hughson 7,70420 silver badges51 bronze badges 18
  • 1 Side note: Should I cast the result of malloc (in C)? – Andreas Wenzel Commented Mar 2 at 23:32
  • 1 @MoragHughson: I recommend that you give the struct the same identifier as the typedef. This will work because in C, these are separate namespaces. So you can simply remove the _ underscore and can use the identifier mySTRING for both the struct and the typedef. This will also work in C++ despite the namespaces not being separate in that language. – Andreas Wenzel Commented Mar 3 at 11:39
  • 1 Related to the comments: stackoverflow/q/44020831/3966456 – Weijun Zhou Commented Mar 3 at 12:15
  • 2 "I know that, in this instance of code, this warning is something I don't need to correct." This assumption is wrong - this code invokes undefined behavior and was always incorrect since it writes out of bounds of an array. And possibly writing data into padding bytes too. Such questionable code was called "the struct hack" back in the 1990s. So this was one of the known problems with C89 which was fixed in the year 1999. Pre-C99, gcc used an extension called zero sized arrays for this purpose. Which all became obsolete with the introduction of flexible array members in C99. – Lundin Commented Mar 4 at 10:23
  • 1 @MoragHughson The warning is correct and shows an incorrect use of strcpy that overflows the destination buffer. Changing from an array of size one to a flexible array member as shown in the answer is changing the meaning of the code - it isn't just cosmetics. – Lundin Commented Mar 4 at 13:00
 |  Show 13 more comments

1 Answer 1

Reset to default 21

You're using what's commonly referred to as the "struct hack" in order to have an array at the end of the struct have a variable size. That method has always been dubious as far as the C standard is concerned.

The proper way to do that as of the C99 standard is with a flexible array member, which leaves the size of the array unspecified:

typedef struct _mySTRING
{
  unsigned short StringLength;
  char           String[];
} mySTRING;

You'll also need to add 1 to the allocated size, as sizeof(mySTRING) doesn't include the String member and you need space for the null terminating byte.

int Needed  = sizeof(mySTRING) + Len + 1;

This makes the rest of your code compliant to the C standard.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745114903a285805.html

最新回复(0)