Skip to content

Commit 8b08f9a

Browse files
authored
enhance error handling and packet validation
Added error handling for null reads and improved packet validation in async_remotejoy, bulk_remotejoy, and do_bulk functions. Introduced a counter for bad protocol packets to manage invalid communication.
1 parent 922f0ea commit 8b08f9a

1 file changed

Lines changed: 185 additions & 37 deletions

File tree

RemoteJoyLite_pc/RemoteJoyLite.cpp

Lines changed: 185 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -108,36 +108,116 @@ static int UsbhostfsReady = 0;
108108
static int UsbhostfsExit = -1;
109109
static int UsbhostError = 0;
110110
static int PSPReady = 0;
111+
static int g_bad_proto_packets = 0;
111112

112113
/*------------------------------------------------------------------------------*/
113114
/* async_remotejoy */
114115
/*------------------------------------------------------------------------------*/
115-
static void async_remotejoy( void *read, int read_len )
116+
static void async_remotejoy(void *read, int read_len)
116117
{
117-
if ( read_len < (int)sizeof(JoyScrHeader) ){ return; }
118-
119-
JoyScrHeader *cmd = (JoyScrHeader *)read;
120-
121-
if ( cmd->mode == ASYNC_CMD_DEBUG ){
122-
dprintf( 0, 0, "%s", (void *)(cmd+1) );
123-
printf("psp debug message begin:\n");
124-
printf("%s", (void *)(cmd + 1));
125-
printf("psp debug message end:\n");
126-
}
118+
if (read == NULL) {
119+
return;
120+
}
121+
122+
if (read_len < (int)sizeof(JoyScrHeader)) {
123+
return;
124+
}
125+
126+
JoyScrHeader *cmd = (JoyScrHeader *)read;
127+
128+
if ((uint32_t)cmd->magic != JOY_MAGIC) {
129+
printf("%s: bad JoyScrHeader.magic: 0x%08X\n",
130+
__func__, (unsigned int)cmd->magic);
131+
return;
132+
}
133+
134+
if (cmd->size < 0) {
135+
printf("%s: negative async payload size: %d\n", __func__, cmd->size);
136+
return;
137+
}
138+
139+
const int payload_available = read_len - (int)sizeof(JoyScrHeader);
140+
if (cmd->size > payload_available) {
141+
printf("%s: truncated async payload: size=%d available=%d\n",
142+
__func__, cmd->size, payload_available);
143+
return;
144+
}
145+
146+
if (cmd->mode == ASYNC_CMD_DEBUG) {
147+
const char *msg = (const char *)(cmd + 1);
148+
149+
// don't assume NULL-terminated string from the device
150+
int safe_len = cmd->size;
151+
while (safe_len > 0 && msg[safe_len - 1] == '\0') {
152+
--safe_len;
153+
}
154+
155+
printf("psp debug message begin:\n");
156+
printf("%.*s", safe_len, msg);
157+
printf("\npsp debug message end:\n");
158+
}
127159
}
128160

129161
/*------------------------------------------------------------------------------*/
130162
/* bulk_remotejoy */
131163
/*------------------------------------------------------------------------------*/
132-
static void bulk_remotejoy( void *read, int read_len )
164+
static void bulk_remotejoy(void *read, int read_len)
133165
{
134-
JoyScrHeader *cmd = (JoyScrHeader *)read;
135-
136-
work.buff_mode = cmd->mode;
137-
work.buff_vcount = cmd->ref;
138-
WaitForSingleObject( work.buff_sema, INFINITE );
139-
memcpy( work.buff, (void *)(cmd+1), cmd->size );
140-
ReleaseSemaphore( work.buff_sema, 1, NULL );
166+
if (read == NULL) {
167+
return;
168+
}
169+
170+
if (read_len < (int)sizeof(JoyScrHeader)) {
171+
printf("%s: short packet (%d < %zu)\n",
172+
__func__, read_len, sizeof(JoyScrHeader));
173+
return;
174+
}
175+
176+
JoyScrHeader *cmd = (JoyScrHeader *)read;
177+
178+
if ((uint32_t)cmd->magic != JOY_MAGIC) {
179+
printf("%s: bad JoyScrHeader.magic: 0x%08X\n",
180+
__func__, (unsigned int)cmd->magic);
181+
return;
182+
}
183+
184+
if (cmd->size < 0) {
185+
printf("%s: negative payload size: %d\n", __func__, cmd->size);
186+
return;
187+
}
188+
189+
const int header_size = (int)sizeof(JoyScrHeader);
190+
const int payload_available = read_len - header_size;
191+
192+
if (cmd->size > payload_available) {
193+
printf("%s: truncated payload: size=%d available=%d\n",
194+
__func__, cmd->size, payload_available);
195+
return;
196+
}
197+
198+
const int max_frame_bytes = (int)sizeof(work.buff);
199+
if (cmd->size > max_frame_bytes) {
200+
printf("%s: oversized frame: size=%d max=%d\n",
201+
__func__, cmd->size, max_frame_bytes);
202+
return;
203+
}
204+
205+
// filter out obviously incorrect modes
206+
// 0..3 = base format, higher bits are used as flags
207+
// leave only log
208+
if ((cmd->mode & 0x0F) > 3) {
209+
printf("%s: suspicious mode: 0x%08X\n",
210+
__func__, (unsigned int)cmd->mode);
211+
return;
212+
}
213+
214+
WaitForSingleObject(work.buff_sema, INFINITE);
215+
216+
work.buff_mode = cmd->mode;
217+
work.buff_vcount = cmd->ref;
218+
memcpy(work.buff, (const void *)(cmd + 1), (size_t)cmd->size);
219+
220+
ReleaseSemaphore(work.buff_sema, 1, NULL);
141221
}
142222

143223
/*------------------------------------------------------------------------------*/
@@ -183,7 +263,24 @@ static void handle_hello( void )
183263
/*------------------------------------------------------------------------------*/
184264
/* do_default */
185265
/*------------------------------------------------------------------------------*/
186-
static void do_default( void *read, int read_len ){}
266+
static void do_default(void *read, int read_len)
267+
{
268+
if (read_len >= 4) {
269+
uint32_t magic = *(uint32_t *)read;
270+
printf("%s: unknown packet magic 0x%08X len=%d\n",
271+
__func__, (unsigned int)magic, read_len);
272+
} else {
273+
printf("%s: tiny unknown packet len=%d\n", __func__, read_len);
274+
}
275+
276+
g_bad_proto_packets++;
277+
278+
if (g_bad_proto_packets >= 8) {
279+
printf("Too many invalid packets; device isn't probably speaking RemoteJoyLite protocol.\n");
280+
UsbhostError = 1;
281+
UsbhostfsExit = 1;
282+
}
283+
}
187284

188285
/*------------------------------------------------------------------------------*/
189286
/* do_hostfs */
@@ -196,6 +293,7 @@ static void do_hostfs( void *read, int read_len )
196293

197294
if ( (int)cmd->command == HOSTFS_CMD_HELLO(RJL_VERSION) ){
198295
UsbhostError = 0;
296+
g_bad_proto_packets = 0;
199297
handle_hello();
200298
} else {
201299
UsbhostError = 1;
@@ -221,24 +319,74 @@ static void do_async( void *read, int read_len )
221319
/*------------------------------------------------------------------------------*/
222320
static char BulkBlock[HOSTFS_BULK_MAXWRITE];
223321

224-
static void do_bulk( void *read, int read_len )
322+
static void do_bulk(void *read, int read_len)
225323
{
226-
BulkCommand *cmd = (BulkCommand *)read;
227-
228-
if ( read_len < (int)sizeof(BulkCommand) ){ return; }
229-
230-
int read_size = 0;
231-
int data_size = cmd->size;
232-
233-
while ( read_size < data_size ){
234-
int rest_size = data_size - read_size;
235-
if ( rest_size > HOSTFS_MAX_BLOCK ){ rest_size = HOSTFS_MAX_BLOCK; }
236-
int ret = usb_bulk_read( UsbDev, 0x81, &BulkBlock[read_size], rest_size, 3000 );
237-
if (ret == -110 || ret == -ETIMEDOUT) {continue;}
238-
if ( ret < 0 ){; break;}
239-
read_size += ret;
240-
}
241-
bulk_remotejoy( BulkBlock, data_size );
324+
if (read == NULL) {
325+
return;
326+
}
327+
328+
if (read_len < (int)sizeof(BulkCommand)) {
329+
printf("%s: short bulk header (%d < %zu)\n",
330+
__func__, read_len, sizeof(BulkCommand));
331+
return;
332+
}
333+
334+
BulkCommand *cmd = (BulkCommand *)read;
335+
336+
if ((uint32_t)cmd->magic != BULK_MAGIC) {
337+
printf("%s: bad BulkCommand.magic: 0x%08X\n",
338+
__func__, (unsigned int)cmd->magic);
339+
return;
340+
}
341+
342+
if ((int32_t)cmd->size < 0) {
343+
printf("%s: negative bulk size: %d\n", __func__, (int32_t)cmd->size);
344+
return;
345+
}
346+
347+
const int data_size = (int)cmd->size;
348+
349+
if (data_size == 0) {
350+
// empty payload - nothing to do
351+
return;
352+
}
353+
354+
if (data_size > (int)sizeof(BulkBlock)) {
355+
printf("%s: bulk payload too large: %d > %zu\n",
356+
__func__, data_size, sizeof(BulkBlock));
357+
return;
358+
}
359+
360+
int read_size = 0;
361+
362+
while (read_size < data_size) {
363+
int rest_size = data_size - read_size;
364+
if (rest_size > HOSTFS_MAX_BLOCK) {
365+
rest_size = HOSTFS_MAX_BLOCK;
366+
}
367+
368+
int ret = usb_bulk_read(UsbDev, 0x81, &BulkBlock[read_size], rest_size, 3000);
369+
370+
if (ret == -110 || ret == -ETIMEDOUT) {
371+
continue;
372+
}
373+
374+
if (ret <= 0) {
375+
printf("%s: usb_bulk_read failed: ret=%d after %d/%d bytes\n",
376+
__func__, ret, read_size, data_size);
377+
return;
378+
}
379+
380+
read_size += ret;
381+
}
382+
383+
if (read_size != data_size) {
384+
printf("%s: incomplete bulk read: got=%d expected=%d\n",
385+
__func__, read_size, data_size);
386+
return;
387+
}
388+
389+
bulk_remotejoy(BulkBlock, data_size);
242390
}
243391

244392
/********************************************************************************/

0 commit comments

Comments
 (0)