From: Mauro Carvalho Chehab Date: Thu, 28 Nov 2013 11:34:15 +0000 (-0200) Subject: libdvbv5: don't use realloc() inside pat.c X-Git-Tag: v4l-utils-1.2.0~282 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aa05eb2cb86860ad9847174e8f46c586ce9c40d8;p=platform%2Fupstream%2Fv4l-utils.git libdvbv5: don't use realloc() inside pat.c The usage of realloc() inside pat is wrong, as the newly reallocated data could have a different address, and this is not returned back to dvb-scan's dvb_read_section_with_id(). While we could do some other tricks to pass the new pointer back, the entire logic is really not good. Also, the PAT handler uses a different model than the other tables. So, change it to use a linked list for the programs. This can, however, break the API for other applications using it. Fortunately, the dvb_pat_program_foreach() macro abstracts this API difference, so, the breakage will not actually happen, if the other apps use this macro (with is the case of tvdaemon). Signed-off-by: Mauro Carvalho Chehab --- diff --git a/lib/include/descriptors/pat.h b/lib/include/descriptors/pat.h index 419e342..edb58c5 100644 --- a/lib/include/descriptors/pat.h +++ b/lib/include/descriptors/pat.h @@ -39,17 +39,17 @@ struct dvb_table_pat_program { uint8_t reserved:3; } __attribute__((packed)); }; + struct dvb_table_pat_program *next; } __attribute__((packed)); struct dvb_table_pat { struct dvb_table_header header; uint16_t programs; - struct dvb_table_pat_program program[]; + struct dvb_table_pat_program *program; } __attribute__((packed)); -#define dvb_pat_program_foreach(_program, _pat) \ - struct dvb_table_pat_program *_program; \ - for (int _i = 0; _i < _pat->programs && (_program = _pat->program + _i); _i++) \ +#define dvb_pat_program_foreach(_pgm, _pat) \ + for (struct dvb_table_pat_program *_pgm = _pat->program; _pgm; _pgm = _pgm->next) \ struct dvb_v5_fe_parms; diff --git a/lib/libdvbv5/descriptors.c b/lib/libdvbv5/descriptors.c index d12119f..7d44653 100644 --- a/lib/libdvbv5/descriptors.c +++ b/lib/libdvbv5/descriptors.c @@ -74,7 +74,7 @@ void dvb_desc_default_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc } const struct dvb_table_init dvb_table_initializers[] = { - [DVB_TABLE_PAT] = { dvb_table_pat_init, 0 /* Size here is variable */ }, + [DVB_TABLE_PAT] = { dvb_table_pat_init, sizeof(struct dvb_table_pat) }, [DVB_TABLE_PMT] = { dvb_table_pmt_init, sizeof(struct dvb_table_pmt) }, [DVB_TABLE_NIT] = { dvb_table_nit_init, sizeof(struct dvb_table_nit) }, [DVB_TABLE_SDT] = { dvb_table_sdt_init, sizeof(struct dvb_table_sdt) }, diff --git a/lib/libdvbv5/descriptors/nit.c b/lib/libdvbv5/descriptors/nit.c index 3cb4dbe..97865d2 100644 --- a/lib/libdvbv5/descriptors/nit.c +++ b/lib/libdvbv5/descriptors/nit.c @@ -90,7 +90,9 @@ void dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize size = offsetof(struct dvb_table_nit_transport, descriptor); while (p + size <= endbuf) { - struct dvb_table_nit_transport *transport = malloc(sizeof(struct dvb_table_nit_transport)); + struct dvb_table_nit_transport *transport; + + transport = malloc(sizeof(struct dvb_table_nit_transport)); if (!transport) dvb_perror("Out of memory"); memcpy(transport, p, size); diff --git a/lib/libdvbv5/descriptors/pat.c b/lib/libdvbv5/descriptors/pat.c index af68b38..2b6fd7f 100644 --- a/lib/libdvbv5/descriptors/pat.c +++ b/lib/libdvbv5/descriptors/pat.c @@ -26,16 +26,16 @@ void dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length) { struct dvb_table_pat *pat = (struct dvb_table_pat *) table; + struct dvb_table_pat_program **head, *last = NULL; + const uint8_t *p = buf, *endbuf = buf + buflen - 4; size_t size; if (*table_length > 0) { - p += offsetof(struct dvb_table_pat, programs); - - size = sizeof(struct dvb_table_pat_program) * pat->programs; - size += buflen; - - pat = realloc(pat, size); + /* find end of current list */ + head = &pat->program; + while (*head != NULL) + head = &(*head)->next; } else { size = offsetof(struct dvb_table_pat, programs); if (p + size > endbuf) { @@ -46,16 +46,33 @@ void dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize memcpy(table, buf, size); p += size; pat->programs = 0; + pat->program = NULL; + head = &pat->program; } - *table_length = buflen + sizeof(uint16_t); + *table_length = sizeof(struct dvb_table_pat_program); - size = sizeof(struct dvb_table_pat_program); + size = offsetof(struct dvb_table_pat_program, next); while (p + size <= endbuf) { - memcpy(pat->program + pat->programs, p, size); - bswap16(pat->program[pat->programs].service_id); - bswap16(pat->program[pat->programs].bitfield); + struct dvb_table_pat_program *pgm; + + pgm = malloc(sizeof(struct dvb_table_pat_program)); + if (!pgm) + dvb_perror("Out of memory"); + + memcpy(pgm, p, size); p += size; + + bswap16(pgm->service_id); + bswap16(pgm->bitfield); pat->programs++; + + pgm->next = NULL; + + if (!*head) + *head = pgm; + if (last) + last->next = pgm; + last = pgm; } if (endbuf - p) dvb_logerr("PAT table has %zu spurious bytes at the end.", @@ -64,17 +81,27 @@ void dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize void dvb_table_pat_free(struct dvb_table_pat *pat) { + struct dvb_table_pat_program *pgm = pat->program; + + while (pgm) { + struct dvb_table_pat_program *tmp = pgm; + pgm = pgm->next; + free(tmp); + } free(pat); } void dvb_table_pat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_pat *pat) { + struct dvb_table_pat_program *pgm = pat->program; + dvb_log("PAT"); dvb_table_header_print(parms, &pat->header); dvb_log("|\\ program service (%d programs)", pat->programs); - int i; - for (i = 0; i < pat->programs; i++) { - dvb_log("|- %7d %7d", pat->program[i].pid, pat->program[i].service_id); + + while (pgm) { + dvb_log("|- %7d %7d", pgm->pid, pgm->service_id); + pgm = pgm->next; } } diff --git a/lib/libdvbv5/dvb-scan.c b/lib/libdvbv5/dvb-scan.c index c5eb68f..978975e 100644 --- a/lib/libdvbv5/dvb-scan.c +++ b/lib/libdvbv5/dvb-scan.c @@ -215,18 +215,9 @@ int dvb_read_section_with_id(struct dvb_v5_fe_parms *parms, int dmx_fd, } } - if (dvb_table_initializers[tid].init) { + if (dvb_table_initializers[tid].init) dvb_table_initializers[tid].init(parms, buf, buf_length, tbl, &table_length); - if (!dvb_table_initializers[tid].size) { - tbl = realloc(tbl, table_length); - if (!tbl) { - dvb_perror("Out of memory"); - free(buf); - dvb_dmx_stop(dmx_fd); - return -4; - } - } - } else + else dvb_logerr("dvb_read_section: no initializer for table %d", tid); if (++sections == last_section + 1)