diff --git a/docs/CHANGES.TXT b/docs/CHANGES.TXT index 19eb08ddb..f96dd2ea5 100644 --- a/docs/CHANGES.TXT +++ b/docs/CHANGES.TXT @@ -6,6 +6,7 @@ - Fix: 32-bit build failures on i686 and armv7l architectures - Fix: Legacy command-line argument compatibility (-1, -2, -12, --sc, --svc) - Fix: Prevent heap buffer overflow in Teletext processing (security fix) +- Fix: Prevent integer overflow leading to heap buffer overflow in Transport Stream handling (security fix) - Fix: Lazy OCR initialization - only initialize when first DVB subtitle is encountered - Build: Optimized Windows CI workflow for faster builds - Fix: Updated GUI with version 0.7.1. A blind attempt to fix a hang on start on some Windows. diff --git a/src/lib_ccx/ccx_decoders_608.c b/src/lib_ccx/ccx_decoders_608.c index 37a057e83..c2b0a0aea 100644 --- a/src/lib_ccx/ccx_decoders_608.c +++ b/src/lib_ccx/ccx_decoders_608.c @@ -316,10 +316,20 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub) if (!data->empty && context->output_format != CCX_OF_NULL) { - struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data)); + size_t new_size; + + if (sub->nb_data + 1 > SIZE_MAX / sizeof(struct eia608_screen)) + { + ccx_common_logging.log_ftn("Too many screens, cannot allocate more memory.\n"); + return 0; + } + + new_size = (sub->nb_data + 1) * sizeof(struct eia608_screen); + + struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, new_size); if (!new_data) { - ccx_common_logging.log_ftn("No Memory left"); + ccx_common_logging.log_ftn("Out of memory while reallocating screen buffer\n"); return 0; } sub->data = new_data; @@ -386,10 +396,20 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub) if (!data->empty) { - struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data)); + size_t new_size; + + if (sub->nb_data + 1 > SIZE_MAX / sizeof(struct eia608_screen)) + { + ccx_common_logging.log_ftn("Too many screens, cannot allocate more memory.\n"); + return 0; + } + + new_size = (sub->nb_data + 1) * sizeof(struct eia608_screen); + + struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, new_size); if (!new_data) { - ccx_common_logging.log_ftn("No Memory left"); + ccx_common_logging.log_ftn("Out of memory while reallocating screen buffer\n"); return 0; } sub->data = new_data; diff --git a/src/lib_ccx/ccx_decoders_isdb.c b/src/lib_ccx/ccx_decoders_isdb.c index 5a1f5f588..5a54340df 100644 --- a/src/lib_ccx/ccx_decoders_isdb.c +++ b/src/lib_ccx/ccx_decoders_isdb.c @@ -724,16 +724,17 @@ static int parse_csi(ISDBSubContext *ctx, const uint8_t *buf, int len) // Copy buf in arg for (i = 0; *buf != 0x20; i++) { - if (i >= (sizeof(arg)) + 1) + if (i >= sizeof(arg) - 1) { - isdb_log("UnExpected CSI %d >= %d", sizeof(arg) + 1, i); + isdb_log("UnExpected CSI: too long"); break; } arg[i] = *buf; buf++; } /* ignore terminating 0x20 character */ - arg[i] = *buf++; + if (i < sizeof(arg)) + arg[i] = *buf++; switch (*buf) { diff --git a/src/lib_ccx/ts_functions.c b/src/lib_ccx/ts_functions.c index 683c4fcf5..2f31b0f78 100644 --- a/src/lib_ccx/ts_functions.c +++ b/src/lib_ccx/ts_functions.c @@ -670,7 +670,6 @@ void cinfo_cremation(struct ccx_demuxer *ctx, struct demuxer_data **data) int copy_payload_to_capbuf(struct cap_info *cinfo, struct ts_payload *payload) { - int newcapbuflen; if (cinfo->ignore == CCX_TRUE && ((cinfo->stream != CCX_STREAM_TYPE_VIDEO_MPEG2 && @@ -696,17 +695,22 @@ int copy_payload_to_capbuf(struct cap_info *cinfo, struct ts_payload *payload) } // copy payload to capbuf - newcapbuflen = cinfo->capbuflen + payload->length; - if (newcapbuflen > cinfo->capbufsize) + if (payload->length > INT64_MAX - cinfo->capbuflen) { - unsigned char *new_capbuf = (unsigned char *)realloc(cinfo->capbuf, newcapbuflen); + mprint("Error: capbuf size overflow\n"); + return -1; + } + int64_t newcapbuflen = (int64_t)cinfo->capbuflen + payload->length; + if (newcapbuflen > (int64_t)cinfo->capbufsize) + { + unsigned char *new_capbuf = (unsigned char *)realloc(cinfo->capbuf, (size_t)newcapbuflen); if (!new_capbuf) return -1; cinfo->capbuf = new_capbuf; - cinfo->capbufsize = newcapbuflen; + cinfo->capbufsize = newcapbuflen; // Note: capbufsize is int in struct cap_info } memcpy(cinfo->capbuf + cinfo->capbuflen, payload->start, payload->length); - cinfo->capbuflen = newcapbuflen; + cinfo->capbuflen = newcapbuflen; // Note: capbuflen is int in struct cap_info return CCX_OK; }