@@ -254,7 +254,9 @@ int parse_PMT(struct ccx_demuxer *ctx, unsigned char *buf, int len, struct progr
254254 ctx -> PIDs_programs [elementary_PID ]-> printable_stream_type = get_printable_stream_type (stream_type );
255255 dbg_print (CCX_DMT_VERBOSE , "%6u | %3X (%3u) | %s\n" , elementary_PID , stream_type , stream_type ,
256256 desc [ctx -> PIDs_programs [elementary_PID ]-> printable_stream_type ]);
257- process_ccx_mpeg_descriptor (buf + i + 5 , ES_info_length );
257+ // Validate ES_info_length against buffer bounds to prevent heap overflow
258+ if (i + 5 + ES_info_length <= len )
259+ process_ccx_mpeg_descriptor (buf + i + 5 , ES_info_length );
258260 i += ES_info_length ;
259261 }
260262 dbg_print (CCX_DMT_VERBOSE , "---\n" );
@@ -275,12 +277,28 @@ int parse_PMT(struct ccx_demuxer *ctx, unsigned char *buf, int len, struct progr
275277 continue ;
276278 }
277279
280+ // Validate ES_info_length against buffer bounds to prevent heap overflow
281+ if (i + 5 + ES_info_length > len )
282+ {
283+ dbg_print (CCX_DMT_GENERIC_NOTICES , "Warning: ES_info_length exceeds buffer, skipping.\n" );
284+ break ;
285+ }
286+
278287 unsigned char * es_info = buf + i + 5 ;
279- for (desc_len = 0 ; (buf + i + 5 + ES_info_length ) > es_info ; es_info += desc_len )
288+ unsigned char * es_info_end = buf + i + 5 + ES_info_length ;
289+ for (desc_len = 0 ; es_info_end > es_info ; es_info += desc_len )
280290 {
291+ // Need at least 2 bytes for descriptor_tag and desc_len
292+ if (es_info + 2 > es_info_end )
293+ break ;
294+
281295 enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor )(* es_info ++ );
282296 desc_len = (* es_info ++ );
283297
298+ // Validate desc_len doesn't exceed remaining buffer
299+ if (es_info + desc_len > es_info_end )
300+ break ;
301+
284302 if (descriptor_tag == CCX_MPEG_DSC_DVB_SUBTITLE )
285303 {
286304 int k = 0 ;
@@ -324,12 +342,29 @@ int parse_PMT(struct ccx_demuxer *ctx, unsigned char *buf, int len, struct progr
324342 if (stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 &&
325343 ES_info_length )
326344 {
345+ // Validate ES_info_length against buffer bounds to prevent heap overflow
346+ if (i + 5 + ES_info_length > len )
347+ {
348+ dbg_print (CCX_DMT_GENERIC_NOTICES , "Warning: ES_info_length exceeds buffer, skipping.\n" );
349+ break ;
350+ }
351+
327352 unsigned char * es_info = buf + i + 5 ;
328- for (desc_len = 0 ; (buf + i + 5 + ES_info_length ) > es_info ; es_info += desc_len )
353+ unsigned char * es_info_end = buf + i + 5 + ES_info_length ;
354+ for (desc_len = 0 ; es_info_end > es_info ; es_info += desc_len )
329355 {
330356 void * ptr ;
357+ // Need at least 2 bytes for descriptor_tag and desc_len
358+ if (es_info + 2 > es_info_end )
359+ break ;
360+
331361 enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor )(* es_info ++ );
332362 desc_len = (* es_info ++ );
363+
364+ // Validate desc_len doesn't exceed remaining buffer
365+ if (es_info + desc_len > es_info_end )
366+ break ;
367+
333368 if (CCX_MPEG_DESC_DATA_COMP == descriptor_tag )
334369 {
335370 int16_t component_id = 0 ;
0 commit comments