The following fixes a crash in ScanStreamData::DeleteCachedTable().
The first call to ATSCStreamData::DeleteCachedTable() can delete the
PSIPTable object. The remaining code will then operate on an invalid object
resulting in undefined behaviour and segmentation faults.
The fix introduces a boolean return value for all DeleteCacheTable() methods
which indicates where an object got deleted (true) or not (false). This way
the caller at least knows what happened and can react properly.
Signed-Off-By: Matthias Dahl <devel@mortal-soul.de>
diff -u a/mythtv/libs/libmythtv/mpeg/atscstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/atscstreamdata.cpp
a
|
b
|
|
761 | 761 | _cached_cvcts[pid] = cvct; |
762 | 762 | } |
763 | 763 | |
764 | | void ATSCStreamData::DeleteCachedTable(PSIPTable *psip) const |
| 764 | bool ATSCStreamData::DeleteCachedTable(PSIPTable *psip) const |
765 | 765 | { |
766 | 766 | if (!psip) |
767 | | return; |
| 767 | return false; |
768 | 768 | |
769 | 769 | QMutexLocker locker(&_cache_lock); |
770 | 770 | if (_cached_ref_cnt[psip] > 0) |
771 | 771 | { |
772 | 772 | _cached_slated_for_deletion[psip] = 1; |
773 | | return; |
| 773 | return false; |
774 | 774 | } |
775 | 775 | else if (TableID::MGT == psip->TableID()) |
776 | 776 | { |
… |
… |
|
792 | 792 | } |
793 | 793 | else |
794 | 794 | { |
795 | | MPEGStreamData::DeleteCachedTable(psip); |
796 | | return; |
| 795 | return MPEGStreamData::DeleteCachedTable(psip); |
797 | 796 | } |
798 | 797 | psip_refcnt_map_t::iterator it; |
799 | 798 | it = _cached_slated_for_deletion.find(psip); |
800 | 799 | if (it != _cached_slated_for_deletion.end()) |
801 | 800 | _cached_slated_for_deletion.erase(it); |
| 801 | |
| 802 | return true; |
802 | 803 | } |
803 | 804 | |
804 | 805 | void ATSCStreamData::ReturnCachedTVCTTables(tvct_vec_t &tvcts) const |
diff -u a/mythtv/libs/libmythtv/mpeg/atscstreamdata.h b/mythtv/libs/libmythtv/mpeg/atscstreamdata.h
a
|
b
|
|
120 | 120 | void CacheTVCT(uint pid, TerrestrialVirtualChannelTable*); |
121 | 121 | void CacheCVCT(uint pid, CableVirtualChannelTable*); |
122 | 122 | protected: |
123 | | virtual void DeleteCachedTable(PSIPTable *psip) const; |
| 123 | virtual bool DeleteCachedTable(PSIPTable *psip) const; |
124 | 124 | |
125 | 125 | private: |
126 | 126 | uint _GPS_UTC_offset; |
diff -u a/mythtv/libs/libmythtv/mpeg/dvbstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/dvbstreamdata.cpp
a
|
b
|
|
853 | 853 | sdts.clear(); |
854 | 854 | } |
855 | 855 | |
856 | | void DVBStreamData::DeleteCachedTable(PSIPTable *psip) const |
| 856 | bool DVBStreamData::DeleteCachedTable(PSIPTable *psip) const |
857 | 857 | { |
858 | 858 | if (!psip) |
859 | | return; |
| 859 | return false; |
860 | 860 | |
861 | 861 | uint tid = psip->TableIDExtension(); |
862 | 862 | |
… |
… |
|
864 | 864 | if (_cached_ref_cnt[psip] > 0) |
865 | 865 | { |
866 | 866 | _cached_slated_for_deletion[psip] = 1; |
867 | | return; |
| 867 | return false; |
868 | 868 | } |
869 | 869 | else if ((TableID::NIT == psip->TableID()) && |
870 | 870 | _cached_nit[psip->Section()]) |
… |
… |
|
880 | 880 | } |
881 | 881 | else |
882 | 882 | { |
883 | | MPEGStreamData::DeleteCachedTable(psip); |
884 | | return; |
| 883 | return MPEGStreamData::DeleteCachedTable(psip); |
885 | 884 | } |
886 | 885 | psip_refcnt_map_t::iterator it; |
887 | 886 | it = _cached_slated_for_deletion.find(psip); |
888 | 887 | if (it != _cached_slated_for_deletion.end()) |
889 | 888 | _cached_slated_for_deletion.erase(it); |
| 889 | |
| 890 | return true; |
890 | 891 | } |
891 | 892 | |
892 | 893 | void DVBStreamData::CacheNIT(NetworkInformationTable *nit) |
diff -u a/mythtv/libs/libmythtv/mpeg/dvbstreamdata.h b/mythtv/libs/libmythtv/mpeg/dvbstreamdata.h
a
|
b
|
|
186 | 186 | void CacheNIT(NetworkInformationTable*); |
187 | 187 | void CacheSDT(ServiceDescriptionTable*); |
188 | 188 | protected: |
189 | | virtual void DeleteCachedTable(PSIPTable *psip) const; |
| 189 | virtual bool DeleteCachedTable(PSIPTable *psip) const; |
190 | 190 | |
191 | 191 | private: |
192 | 192 | /// DVB table monitoring |
diff -u a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
a
|
b
|
|
1405 | 1405 | _cached_ref_cnt[psip] = _cached_ref_cnt[psip] + 1; |
1406 | 1406 | } |
1407 | 1407 | |
1408 | | void MPEGStreamData::DeleteCachedTable(PSIPTable *psip) const |
| 1408 | bool MPEGStreamData::DeleteCachedTable(PSIPTable *psip) const |
1409 | 1409 | { |
1410 | 1410 | if (!psip) |
1411 | | return; |
| 1411 | return false; |
1412 | 1412 | |
1413 | 1413 | uint tid = psip->TableIDExtension(); |
1414 | 1414 | |
… |
… |
|
1416 | 1416 | if (_cached_ref_cnt[psip] > 0) |
1417 | 1417 | { |
1418 | 1418 | _cached_slated_for_deletion[psip] = 1; |
1419 | | return; |
| 1419 | return false; |
1420 | 1420 | } |
1421 | 1421 | else if (TableID::PAT == psip->TableID() && |
1422 | 1422 | (_cached_pats[(tid << 8) | psip->Section()] == psip)) |
… |
… |
|
1433 | 1433 | else |
1434 | 1434 | { |
1435 | 1435 | _cached_slated_for_deletion[psip] = 2; |
1436 | | return; |
| 1436 | return false; |
1437 | 1437 | } |
1438 | 1438 | psip_refcnt_map_t::iterator it; |
1439 | 1439 | it = _cached_slated_for_deletion.find(psip); |
1440 | 1440 | if (it != _cached_slated_for_deletion.end()) |
1441 | 1441 | _cached_slated_for_deletion.erase(it); |
| 1442 | |
| 1443 | return true; |
1442 | 1444 | } |
1443 | 1445 | |
1444 | 1446 | void MPEGStreamData::CachePAT(const ProgramAssociationTable *_pat) |
diff -u a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h
a
|
b
|
|
300 | 300 | |
301 | 301 | // Caching |
302 | 302 | void IncrementRefCnt(const PSIPTable *psip) const; |
303 | | virtual void DeleteCachedTable(PSIPTable *psip) const; |
| 303 | virtual bool DeleteCachedTable(PSIPTable *psip) const; |
304 | 304 | void CachePAT(const ProgramAssociationTable *pat); |
305 | 305 | void CachePMT(const ProgramMapTable *pmt); |
306 | 306 | |
diff -u a/mythtv/libs/libmythtv/mpeg/scanstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/scanstreamdata.cpp
a
|
b
|
|
81 | 81 | } |
82 | 82 | |
83 | 83 | |
84 | | void ScanStreamData::DeleteCachedTable(PSIPTable *psip) const |
| 84 | bool ScanStreamData::DeleteCachedTable(PSIPTable *psip) const |
85 | 85 | { |
86 | 86 | if (!psip) |
87 | | return; |
| 87 | return false; |
88 | 88 | |
89 | | ATSCStreamData::DeleteCachedTable(psip); |
90 | | if (psip->pesdata()) |
91 | | DVBStreamData::DeleteCachedTable(psip); |
| 89 | if (!ATSCStreamData::DeleteCachedTable(psip)) |
| 90 | return DVBStreamData::DeleteCachedTable(psip); |
| 91 | else |
| 92 | return true; |
92 | 93 | } |
diff -u a/mythtv/libs/libmythtv/mpeg/scanstreamdata.h b/mythtv/libs/libmythtv/mpeg/scanstreamdata.h
a
|
b
|
|
29 | 29 | QString GetSIStandard(QString guess = "mpeg") const; |
30 | 30 | |
31 | 31 | private: |
32 | | virtual void DeleteCachedTable(PSIPTable *psip) const; |
| 32 | virtual bool DeleteCachedTable(PSIPTable *psip) const; |
33 | 33 | }; |
34 | 34 | |
35 | 35 | #endif // SCANSTREAMDATA_H_ |