aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>2021-02-23 11:14:07 +0100
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2021-02-23 11:53:05 +0100
commitbe113b1c82e446493aff174f4b9c23617edc74d4 (patch)
treeb03f3153181e6b78179f11d027c1c671f8f47ceb
parent681dd7a93356581d01b118d60e628b04a1c6457a (diff)
downloadv4l-utils-be113b1c82e446493aff174f4b9c23617edc74d4.tar.gz
libdvb: fix ATSC service location parser
A fixup patch actually broke the parser, as it was copying data to the wrong place. Yet, while testing it, it was noticed some streams that have a descriptor 0xa1 whose the language code is bogus: | pcr PID 1539 |\ elementary service - 3 elementaries |- elementary 0 |- | stream type 0x00 |- | PID 1 |- | Language .'. (0xcf 0x27 0x04) |- elementary 1 |- | stream type 0x04 |- | PID 0 |- | Language ..& (0x01 0xcf 0x26) |- elementary 2 |- | stream type 0x05 |- | PID 1280 |- | Language ... (0x00 0x01 0xcf) So, clearly this is not an ATSC descriptor. So, improve the logic to allow displaying invalid language codes, plus check if the descriptor's size is what it was expected. Fixes: 868ca548b10a ("libdvbv5: fix init of the ATSC service location") Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-rw-r--r--lib/include/libdvbv5/desc_atsc_service_location.h2
-rw-r--r--lib/libdvbv5/descriptors/desc_atsc_service_location.c39
2 files changed, 32 insertions, 9 deletions
diff --git a/lib/include/libdvbv5/desc_atsc_service_location.h b/lib/include/libdvbv5/desc_atsc_service_location.h
index 9f864085..f780aa39 100644
--- a/lib/include/libdvbv5/desc_atsc_service_location.h
+++ b/lib/include/libdvbv5/desc_atsc_service_location.h
@@ -57,7 +57,7 @@ struct atsc_desc_service_location_elementary {
uint16_t reserved:3;
} __attribute__((packed));
} __attribute__((packed));
- char ISO_639_language_code[3];
+ unsigned char ISO_639_language_code[3];
} __attribute__((packed));
/**
diff --git a/lib/libdvbv5/descriptors/desc_atsc_service_location.c b/lib/libdvbv5/descriptors/desc_atsc_service_location.c
index 51e48717..8b423dc5 100644
--- a/lib/libdvbv5/descriptors/desc_atsc_service_location.c
+++ b/lib/libdvbv5/descriptors/desc_atsc_service_location.c
@@ -19,6 +19,7 @@
#include <libdvbv5/desc_atsc_service_location.h>
#include <libdvbv5/dvb-fe.h>
+#include <ctype.h>
#if __GNUC__ >= 9
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
@@ -31,16 +32,33 @@ int atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
struct atsc_desc_service_location_elementary *el;
unsigned char *p = (unsigned char *)buf;
int i;
- size_t len;
+ size_t len, dlen = desc->length;
- len = sizeof(*s_loc) - offsetof(struct atsc_desc_service_location, bitfield);
- memcpy(&s_loc, p, len);
+ len = sizeof(*s_loc);
+ if (dlen < len) {
+ dvb_logwarn("ATSC service location descriptor is too small");
+ return -1;
+ }
+
+ memcpy(s_loc, p, len);
p += len;
+ dlen -= len;
bswap16(s_loc->bitfield);
+ len = s_loc->number_elements * sizeof(*s_loc->elementary);
+ if (dlen < len) {
+ dvb_logwarn("ATSC service location descriptor is too small");
+ return -1;
+ }
+ if (dlen > len) {
+ dvb_logwarn("ATSC service location descriptor %zu bytes bigger than expected",
+ dlen - len);
+ return -1;
+ }
+
if (s_loc->number_elements) {
- s_loc->elementary = malloc(s_loc->number_elements * sizeof(*s_loc->elementary));
+ s_loc->elementary = malloc(len);
if (!s_loc->elementary) {
dvb_perror("Can't allocate space for ATSC service location elementary data");
return -1;
@@ -61,6 +79,8 @@ int atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
return 0;
}
+#define prt_char(x) (isprint(x) ? x : '.')
+
void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct atsc_desc_service_location *s_loc = (const struct atsc_desc_service_location *) desc;
@@ -73,10 +93,13 @@ void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struc
dvb_loginfo("|- elementary %d", i);
dvb_loginfo("|- | stream type 0x%02x", el[i].stream_type);
dvb_loginfo("|- | PID %d", el[i].elementary_pid);
- dvb_loginfo("|- | Language %c%c%c",
- el[i].ISO_639_language_code[0],
- el[i].ISO_639_language_code[1],
- el[i].ISO_639_language_code[2]);
+ dvb_loginfo("|- | Language %c%c%c (0x%02x 0x%02x 0x%02x)",
+ prt_char(el[i].ISO_639_language_code[0]),
+ prt_char(el[i].ISO_639_language_code[1]),
+ prt_char(el[i].ISO_639_language_code[2]),
+ el[i].ISO_639_language_code[0],
+ el[i].ISO_639_language_code[1],
+ el[i].ISO_639_language_code[2]);
}
}