I probably found a bug in the openPowerlink Stack 2.0.1 when using the function oplk_sendAsndFrame(). The Stack will be corrupted, when sending ASnd frames greater than 256 Bytes. I couldn't find another way to report a bug so I hope it is ok to do it here.
Lets check the stack definition of the function:
tOplkError oplk_sendAsndFrame(UINT8 dstNodeId_p, tAsndFrame* pAsndFrame_p,
2 tOplkError ret;
3 tFrameInfo frameInfo;
4 BYTE buffer[C_DLL_MAX_ASYNC_MTU]; // C_DLL_MAX_ASYNC_MTU=1500
6 // Calculate size of frame (Asnd data + header)
7 frameInfo.frameSize = asndSize_p + offsetof(tPlkFrame, data);
9 // Check for correct input
10 if ((pAsndFrame_p == NULL) || (frameInfo.frameSize >= sizeof(buffer)))
11 return kErrorReject;
13 // Calculate size of frame (Asnd data + header)
14 frameInfo.frameSize = asndSize_p + offsetof(tPlkFrame, data);
15 frameInfo.pFrame = (tPlkFrame*)buffer;
17 // Copy Asnd data
18 OPLK_MEMSET(frameInfo.pFrame, 0x00, frameInfo.frameSize);
19 OPLK_MEMCPY(&frameInfo.pFrame->data.asnd, pAsndFrame_p, asndSize_p);
21 // Fill in additional data (SrcNodeId is filled by DLL if it is set to 0)
22 ami_setUint8Le(&frameInfo.pFrame->messageType, (UINT8)kMsgTypeAsnd);
23 ami_setUint8Le(&frameInfo.pFrame->dstNodeId, (UINT8)dstNodeId_p);
24 ami_setUint8Le(&frameInfo.pFrame->srcNodeId, (UINT8)0);
26 // Request frame transmission
27 ret = dllucal_sendAsyncFrame(&frameInfo, kDllAsyncReqPrioGeneric);
29 return ret;
In line 4 a buffer with size 1500 for storing the ASnd frame is allocated, followed by some input parameter size checks in the lines 10 and 11. So far so good. The actual error occurs in line 15, where the buffer is casted into a struct which is smaller than 1500 bytes. This finally leads in line 19 to a corrupted stack, when more than 256 bytes are copied into the buffer. In line 19 the member data.asnd is of type tAsndFrame, which is defined as:
UINT8 serviceId; ///< Offset 17
tAsndPayload payload; ///< Offset 18
} PACK_STRUCT tAsndFrame;
with tAsndPayload defined as:
tStatusResponse statusResponse; ///< Offset 18:
UINT8 aPayload; // <-- just 256 Bytes allocated here!!!
where you can see, the buffer of line 4 with 1500 bytes is casted into a struct much to small.
To prevent Stack corruption either the size checks at line 10,11 must address this problem, or (what I prefer, as it allows me to transmitt bigger data) the member aPayload[X] must allocate more memory.
I hope somebody who reads this can explain this problem or forward this bug to the right people.
Thanks for reporting this issue!
We'll verify it and provide a fix in an upcoming version.
the behaviour is intended as it is.
Notice that the structure is used as a pointer, not as an actual variable.
And the buffer that this structure points to is large enough.
The number 256 as size if just a placeholder. We know that we can exceed this limit if the underlying buffer is large enough. This works as aPayload is the last element in the structure hierarchy.
Ok, I think that is the case when using C.
I got the problem because I'm using the openPowerlink stack in a C++ environment. When I try to use oplk_sendAsndFrame() for sending larger packets than 256Byte buffer, I got segmentation fault errors. When I try to do the same trick as shown above, that is allocating a large buffer and then casting it, the compiler wont let me do this because he recognises the space restricted target type of unsigned char.
Maybe there is a way in c++ to perform this cast, but I think the usage here is highly questionable.
A solution would be to define the type of tAsndPayload.aPayload as Pointer type e.g. char* right away, so that this part of code is also semantically c++ compatible.
I would appreciate this change.
Best regards Marcel
Its me again.
My problem is solved, now I can use more than 256Bytes as asynchronous frame size.
I used C++ syntax in a wrong way so the buffer casting had to fail.
So there is nothing wrong with the stack.
But looking at the function again, there is some copy+paste stuff gone wrong ... (frameInfo.frameSize is calculated twice)
I will send a patch.
Log in to post a comment.