diff --git a/src/lib_ccx/avc_functions.c b/src/lib_ccx/avc_functions.c index 0b377bf5e..f9349a42a 100644 --- a/src/lib_ccx/avc_functions.c +++ b/src/lib_ccx/avc_functions.c @@ -392,20 +392,24 @@ void sei_rbsp(struct avc_ctx *ctx, unsigned char *seibuf, unsigned char *seiend) unsigned char *sei_message(struct avc_ctx *ctx, unsigned char *seibuf, unsigned char *seiend) { int payload_type = 0; - while (*seibuf == 0xff) + while (seibuf < seiend && *seibuf == 0xff) { payload_type += 255; seibuf++; } + if (seibuf >= seiend) + return NULL; payload_type += *seibuf; seibuf++; int payload_size = 0; - while (*seibuf == 0xff) + while (seibuf < seiend && *seibuf == 0xff) { payload_size += 255; seibuf++; } + if (seibuf >= seiend) + return NULL; payload_size += *seibuf; seibuf++; diff --git a/src/lib_ccx/ccx_decoders_708.c b/src/lib_ccx/ccx_decoders_708.c index eda2a9b8a..86894f9b0 100644 --- a/src/lib_ccx/ccx_decoders_708.c +++ b/src/lib_ccx/ccx_decoders_708.c @@ -998,6 +998,14 @@ void dtvcc_handle_DFx_DefineWindow(dtvcc_service_decoder *decoder, int window_id int row_count = (data[4] & 0xf) + 1; // according to CEA-708-D int anchor_point = data[4] >> 4; int col_count = (data[5] & 0x3f) + 1; // according to CEA-708-D + + if (row_count > CCX_DTVCC_MAX_ROWS || col_count > CCX_DTVCC_MAX_COLUMNS) + { + ccx_common_logging.log_ftn("[CEA-708] Invalid window size %dx%d (max %dx%d), rejecting window definition\n", + row_count, col_count, CCX_DTVCC_MAX_ROWS, CCX_DTVCC_MAX_COLUMNS); + return; + } + int pen_style = data[6] & 0x7; int win_style = (data[6] >> 3) & 0x7; @@ -1341,6 +1349,14 @@ void dtvcc_handle_SPL_SetPenLocation(dtvcc_service_decoder *decoder, unsigned ch } dtvcc_window *window = &decoder->windows[decoder->current_window]; + if (row >= window->row_count || col >= window->col_count) + { + ccx_common_logging.log_ftn("[CEA-708] dtvcc_handle_SPL_SetPenLocation: " + "Invalid pen location %d:%d for window size %dx%d, rejecting command\n", + row, col, window->row_count, window->col_count); + return; + } + window->pen_row = row; window->pen_column = col; } @@ -1754,6 +1770,12 @@ void dtvcc_process_current_packet(dtvcc_ctx *dtvcc, int len) if (service_number == 7) // There is an extended header { + if (pos + 1 >= dtvcc->current_packet + len) + { + ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_current_packet: " + "Truncated extended header, stopping.\n"); + break; + } pos++; service_number = (pos[0] & 0x3F); // 6 more significant bits // printf ("Extended header: Service number: [%d]\n",service_number); diff --git a/src/lib_ccx/ccx_dtvcc.c b/src/lib_ccx/ccx_dtvcc.c index fa34e1379..be4e33536 100644 --- a/src/lib_ccx/ccx_dtvcc.c +++ b/src/lib_ccx/ccx_dtvcc.c @@ -25,7 +25,7 @@ void dtvcc_process_data(struct dtvcc_ctx *dtvcc, ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: DTVCC Channel Packet Data\n"); if (cc_valid && dtvcc->is_current_packet_header_parsed) { - if (dtvcc->current_packet_length > 253) + if (dtvcc->current_packet_length + 2 > CCX_DTVCC_MAX_PACKET_LENGTH) { ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: " "Warning: Legal packet size exceeded (1), data not added.\n"); @@ -51,7 +51,7 @@ void dtvcc_process_data(struct dtvcc_ctx *dtvcc, ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: DTVCC Channel Packet Start\n"); if (cc_valid) { - if (dtvcc->current_packet_length > CCX_DTVCC_MAX_PACKET_LENGTH - 1) + if (dtvcc->current_packet_length + 2 > CCX_DTVCC_MAX_PACKET_LENGTH) { ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: " "Warning: Legal packet size exceeded (2), data not added.\n"); diff --git a/src/lib_ccx/es_userdata.c b/src/lib_ccx/es_userdata.c index 7e4cac8a9..87e1cfcef 100644 --- a/src/lib_ccx/es_userdata.c +++ b/src/lib_ccx/es_userdata.c @@ -142,7 +142,7 @@ int user_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, struct { if ((ud_header[1] & 0x7F) == 0x01) { - unsigned char cc_data[3 * 31 + 1]; // Maximum cc_count is 31 + unsigned char cc_data[3 * 32]; // Increased for safety margin, 31 is max count dec_ctx->stat_scte20ccheaders++; read_bytes(ustream, 2); // "03 01" @@ -370,6 +370,7 @@ int user_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, struct dbg_print(CCX_DMT_PARSE, "%s", debug_608_to_ASC(dishdata, 0)); dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC(dishdata + 3, 0)); + dishdata[cc_count * 3] = 0xFF; // Ensure termination for store_hdcc store_hdcc(enc_ctx, dec_ctx, dishdata, cc_count, dec_ctx->timing->current_tref, dec_ctx->timing->fts_now, sub); // Ignore 4 (0x020A, followed by two unknown) bytes. @@ -484,7 +485,10 @@ int user_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, struct mprint("MPEG:VBI: only support Luma line\n"); if (udatalen < 720) - mprint("MPEG:VBI: Minimum 720 bytes in luma line required\n"); + { + mprint("MPEG:VBI: Minimum 720 bytes in luma line required, skipping truncated packet.\n"); + return 1; + } decode_vbi(dec_ctx, field, ustream->pos, 720, sub); dbg_print(CCX_DMT_VERBOSE, "GXF (vbi line %d) user data:\n", line_nb); diff --git a/src/lib_ccx/telxcc.c b/src/lib_ccx/telxcc.c index fb32d9dda..7204ac034 100644 --- a/src/lib_ccx/telxcc.c +++ b/src/lib_ccx/telxcc.c @@ -1392,7 +1392,7 @@ int tlt_process_pes_packet(struct lib_cc_decode *dec_ctx, uint8_t *buffer, uint1 uint8_t pes_ext_flag; // extension uint32_t t = 0; - uint16_t i; + uint32_t i; struct TeletextCtx *ctx = dec_ctx->private_data; ctx->sentence_cap = sentence_cap; @@ -1468,6 +1468,9 @@ int tlt_process_pes_packet(struct lib_cc_decode *dec_ctx, uint8_t *buffer, uint1 if (pes_packet_length > size) pes_packet_length = size; + if (size < 9) + return CCX_OK; + // optional PES header marker bits (10.. ....) if ((buffer[6] & 0xc0) == 0x80) { @@ -1480,8 +1483,16 @@ int tlt_process_pes_packet(struct lib_cc_decode *dec_ctx, uint8_t *buffer, uint1 { if ((optional_pes_header_included == YES) && ((buffer[7] & 0x80) > 0)) { - ctx->using_pts = YES; - dbg_print(CCX_DMT_TELETEXT, "- PID 0xbd PTS available\n"); + if (size < 14) + { + ctx->using_pts = NO; + dbg_print(CCX_DMT_TELETEXT, "- PID 0xbd PTS signaled but packet too short, using TS PCR\n"); + } + else + { + ctx->using_pts = YES; + dbg_print(CCX_DMT_TELETEXT, "- PID 0xbd PTS available\n"); + } } else { @@ -1554,11 +1565,17 @@ int tlt_process_pes_packet(struct lib_cc_decode *dec_ctx, uint8_t *buffer, uint1 if (optional_pes_header_included == YES) i += 3 + optional_pes_header_length; - while (i <= pes_packet_length - 6) + while (i + 2 <= pes_packet_length) { uint8_t data_unit_id = buffer[i++]; uint8_t data_unit_len = buffer[i++]; + if (i + data_unit_len > pes_packet_length) + { + dbg_print(CCX_DMT_TELETEXT, "- Teletext data unit length %u exceeds PES packet length, stopping.\n", data_unit_len); + break; + } + if ((data_unit_id == DATA_UNIT_EBU_TELETEXT_NONSUBTITLE) || (data_unit_id == DATA_UNIT_EBU_TELETEXT_SUBTITLE)) { // teletext payload has always size 44 bytes diff --git a/src/lib_ccx/ts_tables.c b/src/lib_ccx/ts_tables.c index 87630b5e4..89611907c 100644 --- a/src/lib_ccx/ts_tables.c +++ b/src/lib_ccx/ts_tables.c @@ -574,6 +574,15 @@ void ts_buffer_psi_packet(struct ccx_demuxer *ctx) else if (ccounter == ctx->PID_buffers[pid]->prev_ccounter + 1 || (ctx->PID_buffers[pid]->prev_ccounter == 0x0f && ccounter == 0)) { ctx->PID_buffers[pid]->prev_ccounter = ccounter; + // Check for integer overflow and reasonable size limit (1MB) + if (ctx->PID_buffers[pid]->buffer_length > 1024 * 1024 || + payload_length > 1024 * 1024 || + ctx->PID_buffers[pid]->buffer_length + payload_length > 1024 * 1024) + { + dbg_print(CCX_DMT_GENERIC_NOTICES, "\rWarning: PSI buffer for PID %u exceeded reasonable limit (1MB), discarding.\n", pid); + return; + } + void *tmp = realloc(ctx->PID_buffers[pid]->buffer, ctx->PID_buffers[pid]->buffer_length + payload_length); if (tmp == NULL) {