Closed stsymbaliuk closed 9 months ago
Hi @stsymbaliuk,
Thank you for this report, clear and concise. Thank you also for the fix proposal.
May I ask you whether you experienced a crash or a stack corruption at run-time or is this an aspect you identified through code review? In the first case, would you mind detailing the procedure to reproduce the issue?
Thank you in advance for your answers.
With regards,
Hi @ALABSTM
I see this problem in runtime. It is hard to debug, as corrupted variable can appear in function that call MSC_File_Operations()
. Before call MSC_File_Operations() locals variable of caller function was saved to stack. As MSC_File_Operations()
don't use stack for other variables except bytesread
it brakes that caller saved variable.
To reproduce I've created a local array of uint16_t bytesread_test[3]
.
Local variables created in stack. And I use array as array elements are unaligned (they located in continues memory region without gaps).
So bytesread_test[1]
used as f_read()
parameter (same way bytesread
was used in original code).
After f_read()
call not only bytesread_test[1]
but bytesread_test[2]
was changed.
So from this you can see that problem exists. Or you can debug original code with code stepping by disassembled code and track stack state before and after MSC_File_Operations()
as I did to find the reason of my problem.
Issue fix described in my first message.
To reproduce problem I've used example project for STM32F769I-Discovery: \STM32Cube\Repository\STM32Cube_FW_F7_V1.16.0\Projects\STM32F769I-Discovery\Applications\USB_Host\MSC_Standalone
Only MSC_File_Operations()
changed to reproduce the issue.
Code that demonstrates the problem. To see fixed code work change USE_CODE_WITH_PROBLEM
to 0
.
void MSC_File_Operations(void)
{
#define USE_CODE_WITH_PROBLEM 1
#if USE_CODE_WITH_PROBLEM
#define INIT_VALUE UINT16_MAX
uint16_t bytesread_test[3] = {INIT_VALUE, INIT_VALUE, INIT_VALUE};
#else
#define INIT_VALUE UINT32_MAX
UINT bytesread_test[3] = {INIT_VALUE, INIT_VALUE, INIT_VALUE};
#endif
LCD_UsrLog("INFO : FatFs Initialized \n");
if (f_open(&MyFile, "0:USBHost.txt", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
LCD_ErrLog("Cannot Open 'USBHost.txt' file \n");
}
else
{
LCD_UsrLog("INFO : 'USBHost.txt' opened for write \n");
res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&bytesWritten);
f_close(&MyFile);
if ((bytesWritten == 0) || (res != FR_OK)) /* EOF or Error */
{
LCD_ErrLog("Cannot Write on the 'USBHost.txt' file \n");
}
else
{
if (f_open(&MyFile, "0:USBHost.txt", FA_READ) != FR_OK)
{
LCD_ErrLog("Cannot Open 'USBHost.txt' file for read.\n");
}
else
{
LCD_UsrLog("INFO : Text written on the 'USBHost.txt' file \n");
#if USE_CODE_WITH_PROBLEM
res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread_test[1]);
#else
res = f_read(&MyFile, rtext, sizeof(rtext), &bytesread_test[1]);
#endif
LCD_DbgLog("bytesread_test[0]: %04x\n", bytesread_test[0]);
LCD_DbgLog("bytesread_test[1]: %04x\n", bytesread_test[1]);
LCD_DbgLog("bytesread_test[2]: %04x\n", bytesread_test[2]);
if (bytesread_test[2] != INIT_VALUE)
{
LCD_DbgLog("Error - Variable in stack changed, bytesread_test[2]: %04x\n", bytesread_test[2]);
}
else
{
LCD_DbgLog("Ok - Variable in stack unchanged, bytesread_test[2]: %04x\n", bytesread_test[2]);
}
if ((bytesread_test[1] == 0) || (res != FR_OK)) /* EOF or Error */
{
LCD_ErrLog("Cannot Read from the 'USBHost.txt' file \n");
}
else
{
LCD_UsrLog("Read Text : \n");
LCD_DbgLog((char *)rtext);
LCD_DbgLog("\n");
}
f_close(&MyFile);
}
/* Compare read data with the expected data */
if ((bytesread_test[1] == bytesWritten))
{
LCD_UsrLog("INFO : FatFs data compare SUCCES");
LCD_UsrLog("\n");
}
else
{
LCD_ErrLog("FatFs data compare ERROR");
LCD_ErrLog("\n");
}
}
}
}
Hi @stsymbaliuk,
I hope you are fine. Allow me first to thank you for all these details and explanations. Your report has been forwarded to our development team. They confirmed the issue. I will get back to you as soon as I have more details.
With regards,
ST Internal Reference: 121879
Fixed in commit 043626d52e34ee8146588bae597513398683e329
Hi @stsymbaliuk,
Back to you about this issue you raised a long time ago. The fix has been finally published. Thank you again for having reported. Spotting the issue was not obvious.
With regards,
There are a lot of same files
file_operations.c
in different projects and different MCU series Cube packages. Now I use F7 and found error inMSC_File_Operations()
all other files have the same problem.Stack corruption caused by
f_read()
which expects 32 bits variable pointer butbytesread
is 16 bits. Whenf_read()
called it overrides 2 bytes ofbytesread
and extra 2 bytes of stack were other variables located.To fix it all
uint16_t bytesread;
must be replaced withUINT bytesread;
Also pointer to void cast should be removed: Replacef_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread)
With:f_read(&MyFile, rtext, sizeof(rtext), &bytesread)
Where I can report this issue to fix it in all files at a time?
file_operations.c
ff.h
integer.h
Also I've checked
sizeof(unsigned int)
Result is: