-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Hi, I recently ran into an issue using XSpiPs_CfgInitialize() where I got undefined behavior. The documentation for the function describes it like so:
Initializes a specific XSpiPs instance such that the driver is ready to use.
With this in mind, for my use case, I stack-allocated an XSpiPs, left it in an uninitialized state (since I expected the API to properly initialize it for me), passed it in and called it a day. Things worked fine for a while, but eventually, I intermittently started receiving XST_DEVICE_IS_STARTED back from it. I was very puzzled until I saw the API's implementation:
s32 XSpiPs_CfgInitialize(XSpiPs *InstancePtr, const XSpiPs_Config *ConfigPtr,
u32 EffectiveAddr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
/*
* If the device is busy, disallow the initialize and return a status
* indicating it is already started. This allows the user to stop the
* device and re-initialize, but prevents a user from inadvertently
* initializing. This assumes the busy flag is cleared at startup.
*/
if (InstancePtr->IsBusy == TRUE) {
Status = (s32)XST_DEVICE_IS_STARTED;
} else {
// start setting default values...
...
}The issue was the if (InstancePtr->IsBusy == TRUE) check reading into my garbage stack memory. Now, I know it's common in C to defensively memset such types to zero them out, so perhaps it was my fault. I'm actually working with the API through Rust FFI so that habit kinda left my mind. I also realize that most users of the API would probably statically-allocate an XSpiPs so that it's initialized to zero naturally, rather than stack-allocate it. Regardless though, I think things like this should be noted in user-facing comments/docs to save them some headache.