@@ -108,36 +108,116 @@ static int UsbhostfsReady = 0;
108108static int UsbhostfsExit = -1 ;
109109static int UsbhostError = 0 ;
110110static 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 (" \n psp 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/* ------------------------------------------------------------------------------*/
222320static 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