mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-04-26 02:02:25 -05:00
FIX: Uninitialized and unaligned reads in LinkWirelessOpenSDK
This commit is contained in:
parent
f7567b489e
commit
aea3ae742a
|
|
@ -613,6 +613,7 @@ enum CommState : unsigned int {
|
|||
- Transfers can contain more than one packet.
|
||||
- As the maximum transfer lengths are `87` (server) and `16` (client), based on header sizes, the maximum payload lengths are `84` and `14`.
|
||||
- The `targetSlots` field inside the server header is a bit array that indicates which clients the message is directed to. E.g. `0b0100` means 'client 2 only' and `0b1111` means 'all clients'.
|
||||
- In `ServerSDKHeader` and `ClientSDKHeader`, all the non-documented bits (including `_unused_`) should be `0`. Otherwise, the official SDK might not respond!
|
||||
|
||||
### (1) Client handshake
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@ static volatile char LINK_WIRELESS_MULTIBOOT_VERSION[] =
|
|||
return lastResult; \
|
||||
}
|
||||
|
||||
#define _LWMNI_ __attribute__((noinline))
|
||||
|
||||
#ifdef LINK_WIRELESS_MULTIBOOT_ENABLE_LOGGING
|
||||
#include <string>
|
||||
#define _LWMLOG_(str) logger(str)
|
||||
|
|
@ -154,13 +152,13 @@ class LinkWirelessMultiboot {
|
|||
* \warning Blocks the system until completion or cancellation.
|
||||
*/
|
||||
template <typename C>
|
||||
_LWMNI_ Result sendRom(const u8* rom,
|
||||
u32 romSize,
|
||||
const char* gameName,
|
||||
const char* userName,
|
||||
const u16 gameId,
|
||||
u8 players,
|
||||
C listener) {
|
||||
Result sendRom(const u8* rom,
|
||||
u32 romSize,
|
||||
const char* gameName,
|
||||
const char* userName,
|
||||
const u16 gameId,
|
||||
u8 players,
|
||||
C listener) {
|
||||
if (romSize < LINK_WIRELESS_MULTIBOOT_MIN_ROM_SIZE)
|
||||
return INVALID_SIZE;
|
||||
if (romSize > LINK_WIRELESS_MULTIBOOT_MAX_ROM_SIZE)
|
||||
|
|
@ -211,7 +209,7 @@ class LinkWirelessMultiboot {
|
|||
volatile Result lastResult;
|
||||
ClientHeader lastValidHeader;
|
||||
|
||||
_LWMNI_ Result activate() {
|
||||
Result activate() {
|
||||
if (!linkRawWireless->activate()) {
|
||||
_LWMLOG_("! adapter not detected");
|
||||
return ADAPTER_NOT_DETECTED;
|
||||
|
|
@ -221,10 +219,10 @@ class LinkWirelessMultiboot {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
_LWMNI_ Result initialize(const char* gameName,
|
||||
const char* userName,
|
||||
const u16 gameId,
|
||||
u8 players) {
|
||||
Result initialize(const char* gameName,
|
||||
const char* userName,
|
||||
const u16 gameId,
|
||||
u8 players) {
|
||||
if (!linkRawWireless->setup(players, SETUP_TX, SETUP_WAIT_TIMEOUT,
|
||||
SETUP_MAGIC)) {
|
||||
_LWMLOG_("! setup failed");
|
||||
|
|
@ -249,7 +247,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result waitForClients(u8 players, C listener) {
|
||||
Result waitForClients(u8 players, C listener) {
|
||||
LinkRawWireless::AcceptConnectionsResponse acceptResponse;
|
||||
|
||||
u32 currentPlayers = 1;
|
||||
|
|
@ -279,7 +277,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result handshakeClient(u8 clientNumber, C listener) {
|
||||
Result handshakeClient(u8 clientNumber, C listener) {
|
||||
ClientPacket handshakePackets[2] = {ClientPacket{}, ClientPacket{}};
|
||||
volatile bool hasReceivedName = false;
|
||||
|
||||
|
|
@ -365,7 +363,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result sendRomStartCommand(C listener) {
|
||||
Result sendRomStartCommand(C listener) {
|
||||
for (u32 i = 0; i < progress.connectedClients; i++) {
|
||||
LINK_WIRELESS_MULTIBOOT_TRY_SUB(exchangeNewData(
|
||||
i,
|
||||
|
|
@ -378,7 +376,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result sendRomBytes(const u8* rom, u32 romSize, C listener) {
|
||||
Result sendRomBytes(const u8* rom, u32 romSize, C listener) {
|
||||
u8 firstPagePatch[LinkWirelessOpenSDK::MAX_PAYLOAD_SERVER];
|
||||
for (u32 i = 0; i < LinkWirelessOpenSDK::MAX_PAYLOAD_SERVER; i++) {
|
||||
firstPagePatch[i] =
|
||||
|
|
@ -415,7 +413,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result confirm(C listener) {
|
||||
Result confirm(C listener) {
|
||||
_LWMLOG_("confirming (1/2)...");
|
||||
for (u32 i = 0; i < progress.connectedClients; i++) {
|
||||
LINK_WIRELESS_MULTIBOOT_TRY_SUB(
|
||||
|
|
@ -440,9 +438,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
_LWMNI_ Result exchangeNewData(u8 clientNumber,
|
||||
SendBuffer sendBuffer,
|
||||
C listener) {
|
||||
Result exchangeNewData(u8 clientNumber, SendBuffer sendBuffer, C listener) {
|
||||
LINK_WIRELESS_MULTIBOOT_TRY_SUB(exchangeData(
|
||||
clientNumber,
|
||||
[this, &sendBuffer](LinkRawWireless::ReceiveDataResponse& response) {
|
||||
|
|
@ -459,9 +455,7 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename V, typename C>
|
||||
_LWMNI_ Result exchangeACKData(u8 clientNumber,
|
||||
V validatePacket,
|
||||
C listener) {
|
||||
Result exchangeACKData(u8 clientNumber, V validatePacket, C listener) {
|
||||
LINK_WIRELESS_MULTIBOOT_TRY_SUB(exchangeData(
|
||||
clientNumber,
|
||||
[this, clientNumber](LinkRawWireless::ReceiveDataResponse& response) {
|
||||
|
|
@ -475,8 +469,10 @@ class LinkWirelessMultiboot {
|
|||
}
|
||||
|
||||
template <typename F, typename V, typename C>
|
||||
_LWMNI_ Result
|
||||
exchangeData(u8 clientNumber, F sendAction, V validatePacket, C listener) {
|
||||
Result exchangeData(u8 clientNumber,
|
||||
F sendAction,
|
||||
V validatePacket,
|
||||
C listener) {
|
||||
volatile bool hasFinished = false;
|
||||
while (!hasFinished) {
|
||||
if (listener(progress))
|
||||
|
|
@ -501,14 +497,13 @@ class LinkWirelessMultiboot {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
_LWMNI_ Result
|
||||
sendAndExpectData(SendBuffer sendBuffer,
|
||||
LinkRawWireless::ReceiveDataResponse& response) {
|
||||
Result sendAndExpectData(SendBuffer sendBuffer,
|
||||
LinkRawWireless::ReceiveDataResponse& response) {
|
||||
return sendAndExpectData(sendBuffer.data, sendBuffer.dataSize,
|
||||
sendBuffer.totalByteCount, response);
|
||||
}
|
||||
|
||||
_LWMNI_ Result sendAndExpectData(
|
||||
Result sendAndExpectData(
|
||||
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data,
|
||||
u32 dataSize,
|
||||
u32 _bytes,
|
||||
|
|
@ -555,7 +550,7 @@ class LinkWirelessMultiboot {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
_LWMNI_ Result ensureAllClientsAreStillAlive() {
|
||||
Result ensureAllClientsAreStillAlive() {
|
||||
LinkRawWireless::SlotStatusResponse slotStatusResponse;
|
||||
if (!linkRawWireless->getSlotStatus(slotStatusResponse))
|
||||
return FAILURE;
|
||||
|
|
@ -566,14 +561,14 @@ class LinkWirelessMultiboot {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
_LWMNI_ Result finish(Result result) {
|
||||
Result finish(Result result) {
|
||||
linkRawWireless->bye();
|
||||
linkRawWireless->deactivate();
|
||||
resetState();
|
||||
return result;
|
||||
}
|
||||
|
||||
_LWMNI_ void resetState() {
|
||||
void resetState() {
|
||||
progress.state = STOPPED;
|
||||
progress.connectedClients = 0;
|
||||
progress.percentage = 0;
|
||||
|
|
@ -602,7 +597,6 @@ class LinkWirelessMultiboot {
|
|||
|
||||
extern LinkWirelessMultiboot* linkWirelessMultiboot;
|
||||
|
||||
#undef _LWMNI_
|
||||
#undef _LWMLOG_
|
||||
|
||||
#endif // LINK_WIRELESS_MULTIBOOT_H
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ class LinkWirelessOpenSDK {
|
|||
static constexpr int MAX_TRANSFER_BYTES_CLIENT = 16;
|
||||
static constexpr int HEADER_SIZE_SERVER = 3;
|
||||
static constexpr int HEADER_SIZE_CLIENT = 2;
|
||||
static constexpr int HEADER_MASK_SERVER = (1 << (HEADER_SIZE_SERVER * 8)) - 1;
|
||||
static constexpr int HEADER_MASK_CLIENT = (1 << (HEADER_SIZE_CLIENT * 8)) - 1;
|
||||
static constexpr int HEADER_MASK_SERVER = 0b1111111111111111111111;
|
||||
static constexpr int HEADER_MASK_CLIENT = 0b11111111111111;
|
||||
static constexpr int MAX_PAYLOAD_SERVER =
|
||||
MAX_TRANSFER_BYTES_SERVER - HEADER_SIZE_SERVER;
|
||||
static constexpr int MAX_PAYLOAD_CLIENT =
|
||||
|
|
@ -161,7 +161,7 @@ class LinkWirelessOpenSDK {
|
|||
ClientPacket* packet =
|
||||
&clientResponse->packets[clientResponse->packetsSize];
|
||||
|
||||
u32 headerInt = *((u16*)(buffer + cursor));
|
||||
u32 headerInt = (buffer[cursor + 1] << 8) | buffer[cursor];
|
||||
packet->header = parseClientHeader(headerInt);
|
||||
cursor += HEADER_SIZE_CLIENT;
|
||||
remainingBytes -= HEADER_SIZE_CLIENT;
|
||||
|
|
@ -202,8 +202,8 @@ class LinkWirelessOpenSDK {
|
|||
ServerPacket* packet =
|
||||
&serverResponse->packets[serverResponse->packetsSize];
|
||||
|
||||
u32 headerInt = (*((u16*)(buffer + cursor))) |
|
||||
(((*((u8*)(buffer + cursor + 2)))) << 16);
|
||||
u32 headerInt = (buffer[cursor + 2] << 16) | (buffer[cursor + 1] << 8) |
|
||||
buffer[cursor];
|
||||
packet->header = parseServerHeader(headerInt);
|
||||
cursor += HEADER_SIZE_SERVER;
|
||||
remainingBytes -= HEADER_SIZE_SERVER;
|
||||
|
|
@ -253,6 +253,7 @@ class LinkWirelessOpenSDK {
|
|||
buffer.header.n = sequence.n;
|
||||
buffer.header.phase = sequence.phase;
|
||||
buffer.header.commState = sequence.commState;
|
||||
buffer.header._unused_ = 0;
|
||||
u32 headerInt = serializeServerHeader(buffer.header);
|
||||
|
||||
buffer.data[buffer.dataSize++] = headerInt;
|
||||
|
|
@ -375,6 +376,7 @@ class LinkWirelessOpenSDK {
|
|||
serverHeader.n = clientHeader.n;
|
||||
serverHeader.phase = clientHeader.phase;
|
||||
serverHeader.commState = clientHeader.commState;
|
||||
serverHeader._unused_ = 0;
|
||||
|
||||
return serverHeader;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user