Fixed a possible crash with inconsistent SI data

This commit is contained in:
Klaus Schmidinger 2004-10-16 10:14:19 +02:00
parent 6415cc900d
commit ac13b6e161
11 changed files with 61 additions and 50 deletions

View File

@ -687,6 +687,7 @@ Marcel Wiesweg <marcel.wiesweg@gmx.de>
for fixing a memory leak in NIT processing for fixing a memory leak in NIT processing
for adding a few missing initializations for adding a few missing initializations
for adding play mode pmVideoOnly for adding play mode pmVideoOnly
for fixing a possible crash with inconsistent SI data
Torsten Herz <torsten.herz@web.de> Torsten Herz <torsten.herz@web.de>
for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu

View File

@ -3006,3 +3006,4 @@ Video Disk Recorder Revision History
testing regarding buffer performance and giving me some hints that finally led testing regarding buffer performance and giving me some hints that finally led
to finding out that this was the basic problem causing buffer overflows). to finding out that this was the basic problem causing buffer overflows).
- Improved Transfer Mode (thanks to Marco Schlüßler for suggestions and testing). - Improved Transfer Mode (thanks to Marco Schlüßler for suggestions and testing).
- Fixed a possible crash with inconsistent SI data (thanks to Marcel Wiesweg).

6
eit.c
View File

@ -8,7 +8,7 @@
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>. * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
* *
* $Id: eit.c 1.96 2004/07/18 10:52:58 kls Exp $ * $Id: eit.c 1.97 2004/10/16 09:49:13 kls Exp $
*/ */
#include "eit.h" #include "eit.h"
@ -47,10 +47,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
bool Modified = false; bool Modified = false;
SI::EIT::Event SiEitEvent; SI::EIT::Event SiEitEvent;
for (SI::Loop::Iterator it; eventLoop.hasNext(it); ) { for (SI::Loop::Iterator it; eventLoop.getNext(SiEitEvent, it); ) {
Empty = false; Empty = false;
SiEitEvent = eventLoop.getNext(it);
cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime()); cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime());
if (!pEvent) { if (!pEvent) {
// If we don't have that event yet, we create a new one. // If we don't have that event yet, we create a new one.

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: descriptor.c 1.13 2004/06/06 14:47:30 kls Exp $ * $Id: descriptor.c 1.14 2004/10/16 09:51:05 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -110,9 +110,7 @@ char *ExtendedEventDescriptors::getText(char *buffer, int size, const char *sepa
continue; continue;
ExtendedEventDescriptor::Item item; ExtendedEventDescriptor::Item item;
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) { for (Loop::Iterator it; d->itemLoop.getNext(item, it); ) {
item=d->itemLoop.getNext(it);
if (!separated && size > sepLen2) { if (!separated && size > sepLen2) {
strcpy(buffer+index, separation2); // let's have a separator between the long text and the items strcpy(buffer+index, separation2); // let's have a separator between the long text and the items
index += sepLen2; index += sepLen2;
@ -207,9 +205,7 @@ char *ExtendedEventDescriptors::getTextItemized(char *buffer, int size, const ch
continue; continue;
ExtendedEventDescriptor::Item item; ExtendedEventDescriptor::Item item;
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) { for (Loop::Iterator it; d->itemLoop.getNext(item, it); ) {
item=d->itemLoop.getNext(it);
item.itemDescription.getText(buffer+index, size); item.itemDescription.getText(buffer+index, size);
len = strlen(buffer+index); len = strlen(buffer+index);
index += len; index += len;
@ -251,9 +247,7 @@ bool ExtendedEventDescriptors::getTextItemized(Loop::Iterator &it, bool &valid,
continue; continue;
ExtendedEventDescriptor::Item item; ExtendedEventDescriptor::Item item;
if (d->itemLoop.hasNext(it)) { if (d->itemLoop.getNext(item, it)) {
item=d->itemLoop.getNext(it);
item.item.getText(itemDescription, sizeItemDescription); item.item.getText(itemDescription, sizeItemDescription);
item.itemDescription.getText(itemText, sizeItemText); item.itemDescription.getText(itemText, sizeItemText);
valid=true; valid=true;

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: si.c 1.11 2004/06/06 14:43:56 kls Exp $ * $Id: si.c 1.12 2004/10/16 09:54:05 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -30,6 +30,10 @@ void Object::setData(CharArray &d) {
data=d; data=d;
} }
bool Object::checkSize(unsigned int offset) {
return data.checkSize(offset);
}
Section::Section(const unsigned char *data, bool doCopy) { Section::Section(const unsigned char *data, bool doCopy) {
setData(data, getLength(data), doCopy); setData(data, getLength(data), doCopy);
} }
@ -50,15 +54,15 @@ int Section::getLength(const unsigned char *d) {
return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader); return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader);
} }
bool CRCSection::isValid() { bool CRCSection::isCRCValid() {
return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/); return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/);
} }
bool CRCSection::CheckCRCAndParse() { bool CRCSection::CheckCRCAndParse() {
if (!isValid()) if (!isCRCValid())
return false; return false;
CheckParse(); CheckParse();
return true; return isValid();
} }
int NumberedSection::getTableIdExtension() const { int NumberedSection::getTableIdExtension() const {
@ -102,7 +106,7 @@ DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) {
} }
Descriptor *DescriptorLoop::getNext(Iterator &it) { Descriptor *DescriptorLoop::getNext(Iterator &it) {
if (it.i<getLength()) { if (isValid() && it.i<getLength()) {
return createDescriptor(it.i, true); return createDescriptor(it.i, true);
} }
return 0; return 0;
@ -110,7 +114,7 @@ Descriptor *DescriptorLoop::getNext(Iterator &it) {
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) { Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
Descriptor *d=0; Descriptor *d=0;
if (it.i<getLength()) { if (isValid() && it.i<getLength()) {
const unsigned char *p=data.getData(it.i); const unsigned char *p=data.getData(it.i);
const unsigned char *end=p+getLength()-it.i; const unsigned char *end=p+getLength()-it.i;
while (p < end) { while (p < end) {
@ -128,7 +132,7 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool return
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) { Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) {
Descriptor *d=0; Descriptor *d=0;
if (it.i<getLength()) { if (isValid() && it.i<getLength()) {
const unsigned char *p=data.getData(it.i); const unsigned char *p=data.getData(it.i);
const unsigned char *end=p+getLength()-it.i; const unsigned char *end=p+getLength()-it.i;
while (p < end) { while (p < end) {
@ -147,6 +151,8 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int array
} }
Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) { Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
if (!checkSize(Descriptor::getLength(data.getData(i))))
return 0;
Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor); Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
if (!d) if (!d)
return 0; return 0;

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: si.h 1.10 2004/06/06 13:35:21 kls Exp $ * $Id: si.h 1.11 2004/10/16 09:58:10 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -180,12 +180,17 @@ public:
//can only be called once since data is immutable //can only be called once since data is immutable
void setData(const unsigned char*data, unsigned int size, bool doCopy=true); void setData(const unsigned char*data, unsigned int size, bool doCopy=true);
CharArray getData() { return data; } CharArray getData() { return data; }
//returns the valid flag which indicates if data is all right or errors have been encountered
bool isValid() { return data.isValid(); }
virtual int getLength() = 0; virtual int getLength() = 0;
protected: protected:
CharArray data; CharArray data;
//is protected - not used for sections //is protected - not used for sections
template <class T> friend class StructureLoop; template <class T> friend class StructureLoop;
void setData(CharArray &d); void setData(CharArray &d);
//returns whether the given offset fits within the limits of the actual data
//The valid flag will be set accordingly
bool checkSize(unsigned int offset);
}; };
class Section : public Object { class Section : public Object {
@ -205,7 +210,7 @@ public:
//convenience: sets data and parses if doParse //convenience: sets data and parses if doParse
CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {} CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
CRCSection() {} CRCSection() {}
bool isValid(); bool isCRCValid();
//convenience: isValid+CheckParse //convenience: isValid+CheckParse
bool CheckCRCAndParse(); bool CheckCRCAndParse();
}; };
@ -229,9 +234,9 @@ public:
class VariableLengthPart : public Object { class VariableLengthPart : public Object {
public: public:
//never forget to call this //never forget to call this
void setData(CharArray d, int l) { Object::setData(d); length=l; } void setData(CharArray d, int l) { Object::setData(d); checkSize(l); length=l; }
//convenience method //convenience method
void setDataAndOffset(CharArray d, int l, unsigned int &offset) { Object::setData(d); length=l; offset+=l; } void setDataAndOffset(CharArray d, int l, unsigned int &offset) { Object::setData(d); checkSize(l); length=l; offset+=l; }
virtual int getLength() { return length; } virtual int getLength() { return length; }
private: private:
int length; int length;
@ -281,29 +286,36 @@ template <class T> class StructureLoop : public Loop {
public: public:
//currently you must use a while-loop testing for hasNext() //currently you must use a while-loop testing for hasNext()
//i must be 0 to get the first descriptor (with the first call) //i must be 0 to get the first descriptor (with the first call)
T getNext(Iterator &it) bool getNext(T &obj, Iterator &it)
{ {
if (!isValid() || it.i >= getLength())
return false;
CharArray d=data; CharArray d=data;
d.addOffset(it.i); d.addOffset(it.i);
T ret; T ret;
ret.setData(d); ret.setData(d);
ret.CheckParse(); ret.CheckParse();
if (!checkSize(ret.getLength()))
return false;
it.i+=ret.getLength(); it.i+=ret.getLength();
return ret; obj=ret;
return true;
} }
T* getNextAsPointer(Iterator &it) T* getNextAsPointer(Iterator &it)
{ {
if (getLength() <= it.i) if (!isValid() || it.i >= getLength())
return 0; return 0;
CharArray d=data; CharArray d=data;
d.addOffset(it.i); d.addOffset(it.i);
T *ret=new T(); T *ret=new T();
ret->setData(d); ret->setData(d);
ret->CheckParse(); ret->CheckParse();
if (!checkSize(ret->getLength()))
return 0;
it.i+=ret->getLength(); it.i+=ret->getLength();
return ret; return ret;
} }
bool hasNext(Iterator &it) { return getLength() > it.i; } //bool hasNext(Iterator &it) { return getLength() > it.i; }
}; };
//contains descriptors of different types //contains descriptors of different types
@ -385,7 +397,7 @@ public:
it.i+=sizeof(T); it.i+=sizeof(T);
return ret; return ret;
} }
bool hasNext(Iterator &it) { return getLength() > it.i; } bool hasNext(Iterator &it) { return isValid() && (getLength() > it.i); }
}; };
class MHP_DescriptorLoop : public DescriptorLoop { class MHP_DescriptorLoop : public DescriptorLoop {

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: util.c 1.3 2003/12/22 14:03:03 kls Exp $ * $Id: util.c 1.4 2004/10/16 09:58:41 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -88,9 +88,7 @@ CharArray CharArray::operator+(const unsigned int offset) const {
return f; return f;
} }
CharArray::Data::Data() : count_(1) { CharArray::Data::Data() : data(0), size(0), count_(1), valid(true) {
size=0;
data=0;
/* /*
lockingPid = 0; lockingPid = 0;
locked = 0; locked = 0;

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: util.h 1.3 2003/12/22 14:07:41 kls Exp $ * $Id: util.h 1.4 2004/10/16 09:59:48 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -58,6 +58,9 @@ public:
u_int16_t TwoBytes(const unsigned int index) const { return data_->data ? data_->TwoBytes(off+index) : 0; } u_int16_t TwoBytes(const unsigned int index) const { return data_->data ? data_->TwoBytes(off+index) : 0; }
u_int32_t FourBytes(const unsigned int index) const { return data_->data ? data_->FourBytes(off+index) : 0; } u_int32_t FourBytes(const unsigned int index) const { return data_->data ? data_->FourBytes(off+index) : 0; }
bool isValid() const { return data_->valid; }
bool checkSize(unsigned int offset) { return (data_->valid && (data_->valid=(off+offset < data_->size))); }
void addOffset(unsigned int offset) { off+=offset; } void addOffset(unsigned int offset) { off+=offset; }
private: private:
class Data { class Data {
@ -86,10 +89,12 @@ private:
const unsigned char*data; const unsigned char*data;
unsigned int size; unsigned int size;
unsigned count_;
// count_ is the number of CharArray objects that point at this // count_ is the number of CharArray objects that point at this
// count_ must be initialized to 1 by all constructors // count_ must be initialized to 1 by all constructors
// (it starts as 1 since it is pointed to by the CharArray object that created it) // (it starts as 1 since it is pointed to by the CharArray object that created it)
unsigned count_;
bool valid;
/* /*
pthread_mutex_t mutex; pthread_mutex_t mutex;

6
nit.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: nit.c 1.8 2004/06/06 14:24:49 kls Exp $ * $Id: nit.c 1.9 2004/10/16 10:00:27 kls Exp $
*/ */
#include "nit.h" #include "nit.h"
@ -92,8 +92,8 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
return; return;
if (!Channels.Lock(true, 10)) if (!Channels.Lock(true, 10))
return; return;
for (SI::Loop::Iterator it; nit.transportStreamLoop.hasNext(it); ) { SI::NIT::TransportStream ts;
SI::NIT::TransportStream ts = nit.transportStreamLoop.getNext(it); for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) {
SI::Descriptor *d; SI::Descriptor *d;
for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) { for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) {
switch (d->getDescriptorTag()) { switch (d->getDescriptorTag()) {

8
pat.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: pat.c 1.9 2004/05/23 09:29:04 kls Exp $ * $Id: pat.c 1.10 2004/10/16 10:01:12 kls Exp $
*/ */
#include "pat.h" #include "pat.h"
@ -285,8 +285,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
return; return;
SI::PAT::Association assoc; SI::PAT::Association assoc;
int Index = 0; int Index = 0;
for (SI::Loop::Iterator it; pat.associationLoop.hasNext(it); ) { for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
assoc = pat.associationLoop.getNext(it);
if (!assoc.isNITPid()) { if (!assoc.isNITPid()) {
if (Index++ == pmtIndex) { if (Index++ == pmtIndex) {
pmtPid = assoc.getPid(); pmtPid = assoc.getPid();
@ -332,8 +331,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
int Tpid = 0; int Tpid = 0;
int NumApids = 0; int NumApids = 0;
int NumDpids = 0; int NumDpids = 0;
for (SI::Loop::Iterator it; pmt.streamLoop.hasNext(it); ) { for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
stream = pmt.streamLoop.getNext(it);
switch (stream.getStreamType()) { switch (stream.getStreamType()) {
case 1: // STREAMTYPE_11172_VIDEO case 1: // STREAMTYPE_11172_VIDEO
case 2: // STREAMTYPE_13818_VIDEO case 2: // STREAMTYPE_13818_VIDEO

10
sdt.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: sdt.c 1.11 2004/07/18 11:14:42 kls Exp $ * $Id: sdt.c 1.12 2004/10/16 10:02:23 kls Exp $
*/ */
#include "sdt.h" #include "sdt.h"
@ -39,9 +39,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
if (!Channels.Lock(true, 10)) if (!Channels.Lock(true, 10))
return; return;
SI::SDT::Service SiSdtService; SI::SDT::Service SiSdtService;
for (SI::Loop::Iterator it; sdt.serviceLoop.hasNext(it); ) { for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
SiSdtService = sdt.serviceLoop.getNext(it);
cChannel *channel = Channels.GetByChannelID(tChannelID(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId())); cChannel *channel = Channels.GetByChannelID(tChannelID(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()));
if (!channel) if (!channel)
channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId())); channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId()));
@ -110,8 +108,8 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
*/ */
case SI::NVODReferenceDescriptorTag: { case SI::NVODReferenceDescriptorTag: {
SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d; SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d;
for (SI::Loop::Iterator it; nrd->serviceLoop.hasNext(it); ) { SI::NVODReferenceDescriptor::Service Service;
SI::NVODReferenceDescriptor::Service Service = nrd->serviceLoop.getNext(it); for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId())); cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
if (!link && Setup.UpdateChannels >= 3) { if (!link && Setup.UpdateChannels >= 3) {
link = Channels.NewChannel(Channel(), "NVOD", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()); link = Channels.NewChannel(Channel(), "NVOD", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());