From 81cf7a58f00005b21520fab240a3427a119e7bde Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Roth?= Date: Wed, 16 Apr 2014 18:22:10 -0300 Subject: [PATCH] libdvbv5: improve DVB header handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit the table parsers now initialize the complete table, and do no longer rely on an already initialized table header in the supplied buffer. adds section length checking in PAT as well. Signed-off-by: André Roth Signed-off-by: Mauro Carvalho Chehab --- lib/include/libdvbv5/header.h | 2 +- lib/libdvbv5/dvb-scan.c | 31 +++++++++++++++---------------- lib/libdvbv5/tables/atsc_eit.c | 1 + lib/libdvbv5/tables/cat.c | 1 + lib/libdvbv5/tables/eit.c | 1 + lib/libdvbv5/tables/header.c | 3 +-- lib/libdvbv5/tables/mgt.c | 1 + lib/libdvbv5/tables/nit.c | 1 + lib/libdvbv5/tables/pat.c | 11 ++++++++++- lib/libdvbv5/tables/pmt.c | 1 + lib/libdvbv5/tables/sdt.c | 1 + lib/libdvbv5/tables/vct.c | 1 + 12 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/include/libdvbv5/header.h b/lib/include/libdvbv5/header.h index dc85f46..856e4dc 100644 --- a/lib/include/libdvbv5/header.h +++ b/lib/include/libdvbv5/header.h @@ -71,7 +71,7 @@ struct dvb_v5_fe_parms; extern "C" { #endif -int dvb_table_header_init (struct dvb_table_header *t); +void dvb_table_header_init (struct dvb_table_header *t); void dvb_table_header_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_header *t); #ifdef __cplusplus diff --git a/lib/libdvbv5/dvb-scan.c b/lib/libdvbv5/dvb-scan.c index f849176..76d963d 100644 --- a/lib/libdvbv5/dvb-scan.c +++ b/lib/libdvbv5/dvb-scan.c @@ -167,39 +167,38 @@ void dvb_table_filter_free(struct dvb_table_filter *sect) static int dvb_parse_section(struct dvb_v5_fe_parms *parms, struct dvb_table_filter *sect, - uint8_t *buf, ssize_t buf_length) + const uint8_t *buf, ssize_t buf_length) { - struct dvb_table_header *h; + struct dvb_table_header h; struct dvb_table_filter_priv *priv; - unsigned char tid; - h = (struct dvb_table_header *)buf; - dvb_table_header_init(h); + memcpy(&h, buf, sizeof(struct dvb_table_header)); + dvb_table_header_init(&h); if (parms->verbose) dvb_log("%s: received table 0x%02x, TS ID 0x%04x, section %d/%d", - __func__, h->table_id, h->id, h->section_id, h->last_section); + __func__, h.table_id, h.id, h.section_id, h.last_section); - if (sect->tid != h->table_id) { + if (sect->tid != h.table_id) { dvb_logdbg("%s: couldn't match ID %d at the active section filters", - __func__, h->table_id); + __func__, h.table_id); return -1; } priv = sect->priv; - tid = h->table_id; + tid = h.table_id; if (priv->first_ts_id < 0) - priv->first_ts_id = h->id; + priv->first_ts_id = h.id; if (priv->first_section < 0) - priv->first_section = h->section_id; + priv->first_section = h.section_id; if (priv->last_section < 0) - priv->last_section = h->last_section; + priv->last_section = h.last_section; else { /* Check if the table was already parsed, but not on first pass */ if (!sect->allow_section_gaps && sect->ts_id != -1) { - if (test_bit(h->section_id, priv->is_read_bits)) + if (test_bit(h.section_id, priv->is_read_bits)) return 0; - } else if (priv->first_ts_id == h->id && priv->first_section == h->section_id) { + } else if (priv->first_ts_id == h.id && priv->first_section == h.section_id) { /* tables like EIT can increment sections by gaps > 1. * in this case, reading is done when a already read * table is reached. */ @@ -212,13 +211,13 @@ static int dvb_parse_section(struct dvb_v5_fe_parms *parms, /* search for an specific TS ID */ if (sect->ts_id != -1) { - if (h->id != sect->ts_id) + if (h.id != sect->ts_id) return 0; } /* handle the sections */ if (!sect->allow_section_gaps && sect->ts_id != -1) - set_bit(h->section_id, priv->is_read_bits); + set_bit(h.section_id, priv->is_read_bits); if (dvb_table_initializers[tid]) dvb_table_initializers[tid](parms, buf, buf_length - DVB_CRC_SIZE, diff --git a/lib/libdvbv5/tables/atsc_eit.c b/lib/libdvbv5/tables/atsc_eit.c index ab05c30..12179e6 100644 --- a/lib/libdvbv5/tables/atsc_eit.c +++ b/lib/libdvbv5/tables/atsc_eit.c @@ -53,6 +53,7 @@ ssize_t atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, eit = *table; memcpy(eit, p, size); p += size; + dvb_table_header_init(&eit->header); /* find end of curent list */ head = &eit->event; diff --git a/lib/libdvbv5/tables/cat.c b/lib/libdvbv5/tables/cat.c index e7a9c04..7084a8e 100644 --- a/lib/libdvbv5/tables/cat.c +++ b/lib/libdvbv5/tables/cat.c @@ -52,6 +52,7 @@ ssize_t dvb_table_cat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, cat = *table; memcpy(cat, p, size); p += size; + dvb_table_header_init(&cat->header); /* find end of current lists */ head_desc = &cat->descriptor; diff --git a/lib/libdvbv5/tables/eit.c b/lib/libdvbv5/tables/eit.c index f81ff7b..4e5d35b 100644 --- a/lib/libdvbv5/tables/eit.c +++ b/lib/libdvbv5/tables/eit.c @@ -56,6 +56,7 @@ ssize_t dvb_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, eit = *table; memcpy(eit, p, size); p += size; + dvb_table_header_init(&eit->header); bswap16(eit->transport_id); bswap16(eit->network_id); diff --git a/lib/libdvbv5/tables/header.c b/lib/libdvbv5/tables/header.c index ef55221..64af8cd 100644 --- a/lib/libdvbv5/tables/header.c +++ b/lib/libdvbv5/tables/header.c @@ -22,11 +22,10 @@ #include #include -int dvb_table_header_init(struct dvb_table_header *t) +void dvb_table_header_init(struct dvb_table_header *t) { bswap16(t->bitfield); bswap16(t->id); - return 0; } void dvb_table_header_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_header *t) diff --git a/lib/libdvbv5/tables/mgt.c b/lib/libdvbv5/tables/mgt.c index a562ed7..febfd51 100644 --- a/lib/libdvbv5/tables/mgt.c +++ b/lib/libdvbv5/tables/mgt.c @@ -54,6 +54,7 @@ ssize_t atsc_table_mgt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, mgt = *table; memcpy(mgt, p, size); p += size; + dvb_table_header_init(&mgt->header); bswap16(mgt->tables); diff --git a/lib/libdvbv5/tables/nit.c b/lib/libdvbv5/tables/nit.c index ad58436..1fdb035 100644 --- a/lib/libdvbv5/tables/nit.c +++ b/lib/libdvbv5/tables/nit.c @@ -53,6 +53,7 @@ ssize_t dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, nit = *table; memcpy(nit, p, size); p += size; + dvb_table_header_init(&nit->header); bswap16(nit->bitfield); diff --git a/lib/libdvbv5/tables/pat.c b/lib/libdvbv5/tables/pat.c index 0b497bf..a51a11d 100644 --- a/lib/libdvbv5/tables/pat.c +++ b/lib/libdvbv5/tables/pat.c @@ -53,12 +53,21 @@ ssize_t dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, pat = *table; memcpy(pat, buf, size); p += size; + dvb_table_header_init(&pat->header); /* find end of current list */ head = &pat->program; while (*head != NULL) head = &(*head)->next; + size = pat->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */ + if (buf + size > endbuf) { + dvb_logerr("%s: short read %zd/%zd bytes", __func__, + endbuf - buf, size); + return -4; + } + endbuf = buf + size; + size = offsetof(struct dvb_table_pat_program, next); while (p + size <= endbuf) { struct dvb_table_pat_program *prog; @@ -66,7 +75,7 @@ ssize_t dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, prog = malloc(sizeof(struct dvb_table_pat_program)); if (!prog) { dvb_logerr("%s: out of memory", __func__); - return -4; + return -5; } memcpy(prog, p, size); diff --git a/lib/libdvbv5/tables/pmt.c b/lib/libdvbv5/tables/pmt.c index 1fe2a91..8f048c2 100644 --- a/lib/libdvbv5/tables/pmt.c +++ b/lib/libdvbv5/tables/pmt.c @@ -56,6 +56,7 @@ ssize_t dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, pmt = *table; memcpy(pmt, p, size); p += size; + dvb_table_header_init(&pmt->header); bswap16(pmt->bitfield); bswap16(pmt->bitfield2); diff --git a/lib/libdvbv5/tables/sdt.c b/lib/libdvbv5/tables/sdt.c index 9d07ecb..a07b342 100644 --- a/lib/libdvbv5/tables/sdt.c +++ b/lib/libdvbv5/tables/sdt.c @@ -53,6 +53,7 @@ ssize_t dvb_table_sdt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, sdt = *table; memcpy(sdt, p, size); p += size; + dvb_table_header_init(&sdt->header); bswap16(sdt->network_id); /* find end of curent list */ diff --git a/lib/libdvbv5/tables/vct.c b/lib/libdvbv5/tables/vct.c index 21554a4..17687a6 100644 --- a/lib/libdvbv5/tables/vct.c +++ b/lib/libdvbv5/tables/vct.c @@ -55,6 +55,7 @@ ssize_t atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, vct = *table; memcpy(vct, p, size); p += size; + dvb_table_header_init(&vct->header); /* find end of curent list */ head = &vct->channel; -- 2.7.4