3

Facing a warning which I am not able to resolve. I am using stm32 MCU and STM32CubeIDE with a standard C11 compiler. I can easily get rid of the warning by increasing size of the array gStr but would like to know what is the issue here. Current size of gStr looks adequate to hold the given data. Any help is appreciated. Thank you!

The global definitions of the variables used looks like this:

#define LOG_ERROR_FILENAME_MAX_LEN  30
#define LOG_ERROR_MAX_ENTRY 30
#define LOG_GSTR_SIZE   128     //changed from 128 to 2048 to remove warning

typedef struct
{
    char fileName[LOG_ERROR_FILENAME_MAX_LEN];
    u16 line;
    u16 hits;
} LogEntryType;

static LogEntryType gLogEntrys[LOG_ERROR_MAX_ENTRY];
u8 gLogEntryCount = 0;
static char gStr[LOG_GSTR_SIZE];

The function call where the warning is generated looks like this:

snprintf(gStr, LOG_GSTR_SIZE, "%s line:%u hits:%u",gLogEntrys[i].fileName, gLogEntrys[i].line, gLogEntrys[i].hits);

The snprintf call is generating the following warning

../User/Utils/log_error.c: In function 'cliCmdDisplayLog':
../User/Utils/log_error.c:54:36: **warning**: '%s' directive output may be truncated writing up to 1019 bytes into a region of size 128 [-Wformat-truncation=]
   54 |     snprintf(gStr, LOG_GSTR_SIZE, "%s line:%u hits:%u",
      |                                    ^~
../User/Utils/log_error.c:54:35: note: directive argument in the range [0, 65535]
   54 |     snprintf(gStr, LOG_GSTR_SIZE, "%s line:%u hits:%u",
      |                                   ^~~~~~~~~~~~~~~~~~~~
../User/Utils/log_error.c:54:35: note: directive argument in the range [1, 65535]
../User/Utils/log_error.c:54:5: note: 'snprintf' output between 15 and 1042 bytes into a destination of size 128
   54 |     snprintf(gStr, LOG_GSTR_SIZE, "%s line:%u hits:%u",
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   55 |      gLogEntrys[i].fileName, gLogEntrys[i].line, gLogEntrys[i].hits);
      |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EmbeddedManiac
  • 189
  • 1
  • 12
  • Sure seems like a stupid warning to me - the entire **point** of using `snprintf()` is so the resulting string is truncated and doesn't overflow the buffer. Frankly, I'd submit a bug report to the compiler vendor. Might as well emit a warning for every integer addition or multiplication operation that it could overflow and invoke undefined behavior. – Andrew Henle Mar 01 '22 at 22:08
  • @AndrewHenle: I suppose it depends on whether or not the truncation is there to protect memory or as a "feature" of your program. – Robert Harvey Mar 01 '22 at 22:11
  • @RobertHarvey The entire point of `snprintf()` is to never write more than the specified number of `char`s to the buffer. This warning amounts to "working as designed". – Andrew Henle Mar 01 '22 at 22:12
  • Seems like there's some static code analysis going on here. *"note: 'snprintf' output between 15 and 1042 bytes into a destination of size 128"* – Robert Harvey Mar 01 '22 at 22:14
  • And yes, if the compiler is smart enough to figure that out, I'd definitely prefer to know about it. – Robert Harvey Mar 01 '22 at 22:15
  • 5
    I suspect that this may be [GCC bug 95755](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95755), or closely related to it. – Jonathan Leffler Mar 01 '22 at 22:15
  • 1
    @RobertHarvey 15 is the amount of chars it would write with 0s in the integers and empty string. I don't know from where the total of 1042 comes from (especially when the single string is limited to 30 bytes). – Roberto Caboni Mar 01 '22 at 22:17
  • Edit the question to provide a [mre]. – Eric Postpischil Mar 01 '22 at 22:27
  • 1
    I read the about the subtle bug in the link. So the workaround would be something like `sprintf( format, ""%%.%us line:%%u hits:%%u", LOG_ERROR_FILENAME_MAX_LEN-1);` to prepare the format string according to the length written in the define and `snprintf(gStr, LOG_GSTR_SIZE, format,gLogEntrys[i].fileName, gLogEntrys[i].line, gLogEntrys[i].hits);` to actually print it? I leave the answer to you, @JonathanLeffler – Roberto Caboni Mar 01 '22 at 22:27
  • It seems the compiler believes the `fileName` array is 1020 bytes long, and it assumes your file name could be as long as 1019 bytes as a result. The reason for 1020 appears to be from the fact that your `gLogEntries` array starting address is the same as the starting address of `gLogEntries[0].fileName`. – jxh Mar 02 '22 at 03:48

1 Answers1

4

Judging from the symptoms, I think your problem is a variant of the problem reported to GCC as GCC Bug 95755, reported in June 2020 but not yet fixed.

There is an outline workaround in the response to the report. You would need to use limits in the format strings (%*.*s or %.*s with integers specifying the length), or you'd need to create the format string on the fly with one snprintf() operation creating the format string and a second using it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278