@@ -615,6 +615,20 @@ void AVContext::clear_pes(uint16_t channel)
615615 * AVCONTEXT_TS_ERROR
616616 * Parsing error !
617617 */
618+ // MPEG-2 systems CRC-32 (poly 0x04C11DB7, MSB-first, init 0xFFFFFFFF, no final
619+ // XOR / no reflection). Computing it over a whole PSI section (table_id .. CRC)
620+ // yields 0 when the section is intact.
621+ static uint32_t crc32_mpeg (uint32_t crc, const unsigned char * data, size_t len)
622+ {
623+ for (size_t i = 0 ; i < len; ++i)
624+ {
625+ crc ^= static_cast <uint32_t >(data[i]) << 24 ;
626+ for (int b = 0 ; b < 8 ; ++b)
627+ crc = (crc & 0x80000000 ) ? ((crc << 1 ) ^ 0x04c11db7 ) : (crc << 1 );
628+ }
629+ return crc;
630+ }
631+
618632int AVContext::parse_ts_psi ()
619633{
620634 size_t len;
@@ -691,6 +705,36 @@ int AVContext::parse_ts_psi()
691705 }
692706
693707 // now entire table is filled
708+
709+ // Validate the section CRC32 before trusting it. Every PSI section (PAT/PMT)
710+ // is protected by a trailing CRC32; random TS payload that merely began with a
711+ // PSI-like table_id will not satisfy it. Without this check such payload is
712+ // misparsed as a PAT/PMT, spuriously (de)registers streams / forces a program
713+ // change, corrupts the demux state and can crash on the next resync. This also
714+ // lets us safely accept a PMT carried on a non-standard PID (issue #2010).
715+ {
716+ const uint16_t section_len = this ->packet ->packet_table .len ;
717+ if (section_len < 4 || section_len > TABLE_BUFFER_SIZE )
718+ return AVCONTEXT_TS_ERROR ;
719+ // The 3-byte section header (table_id + syntax/length word) is not kept in
720+ // buf; reconstruct it (PAT/PMT are long syntax sections, top bits '1011').
721+ const unsigned char header[3 ] = {
722+ this ->packet ->packet_table .table_id ,
723+ static_cast <unsigned char >(0xb0 | ((section_len >> 8 ) & 0x0f )),
724+ static_cast <unsigned char >(section_len & 0xff )
725+ };
726+ uint32_t crc = 0xffffffff ;
727+ crc = crc32_mpeg (crc, header, 3 );
728+ crc = crc32_mpeg (crc, this ->packet ->packet_table .buf , section_len);
729+ if (crc != 0 )
730+ {
731+ DBG (DEMUX_DBG_DEBUG , " %s: bad PSI CRC on pid %.4x table_id %.2x; ignoring section\n " ,
732+ __FUNCTION__, this ->packet ->pid , this ->packet ->packet_table .table_id );
733+ this ->packet ->packet_table .Reset ();
734+ return AVCONTEXT_CONTINUE ;
735+ }
736+ }
737+
694738 const unsigned char * psi = this ->packet ->packet_table .buf ;
695739 const unsigned char * end_psi = psi + this ->packet ->packet_table .len ;
696740
0 commit comments