mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-07-08 18:06:30 +00:00
Fix unchecked strdup() return values in lib_ccx (#2213)
Two related strdup bugs across multiple lib_ccx files:
1. strdup(variable) return not checked for NULL — use after potential
NULL dereference causes undefined behavior / segfault on OOM.
Fixed by adding NULL check + fatal(EXIT_NOT_ENOUGH_MEMORY, ...).
2. strdup("literal") in get_buffer_type_str returned directly as
function result — unchecked and leaks memory on every call since
the function has no callers that free it. Fixed by removing strdup
and returning string literals directly; return type changed from
char * to const char * (no callers exist, no header declaration).
Files changed:
src/lib_ccx/ccx_common_common.c
src/lib_ccx/ccx_encoders_common.c
src/lib_ccx/ccx_encoders_helpers.c
src/lib_ccx/configuration.c
src/lib_ccx/hardsubx.c
src/lib_ccx/hardsubx_decoder.c
src/lib_ccx/ocr.c
src/lib_ccx/output.c
src/lib_ccx/ts_functions.c
Fixes #2194
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,9 @@ int add_cc_sub_text(struct cc_subtitle *sub, char *str, LLONG start_time,
|
||||
sub->type = CC_TEXT;
|
||||
sub->enc_type = e_type;
|
||||
sub->data = strdup(str);
|
||||
if (sub->data == NULL)
|
||||
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In add_cc_sub_text: Not enough memory for subtitle data.\n");
|
||||
sub->datatype = CC_DATATYPE_GENERIC;
|
||||
sub->nb_data = str ? strlen(str) : 0;
|
||||
sub->start_time = start_time;
|
||||
|
||||
@@ -607,7 +607,11 @@ static int init_output_ctx(struct encoder_ctx *ctx, struct encoder_cfg *cfg)
|
||||
char *basefilename = get_basename(cfg->output_filename);
|
||||
extension = get_file_extension(cfg->write_format);
|
||||
|
||||
ret = init_write(&ctx->out[0], strdup(cfg->output_filename), cfg->with_semaphore);
|
||||
char *fname0 = strdup(cfg->output_filename);
|
||||
if (fname0 == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In init_output_ctx: Not enough memory for output filename.\n");
|
||||
ret = init_write(&ctx->out[0], fname0, cfg->with_semaphore);
|
||||
check_ret(cfg->output_filename);
|
||||
ret = init_write(&ctx->out[1], create_outfilename(basefilename, "_2", extension), cfg->with_semaphore);
|
||||
check_ret(ctx->out[1].filename);
|
||||
@@ -615,7 +619,11 @@ static int init_output_ctx(struct encoder_ctx *ctx, struct encoder_cfg *cfg)
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = init_write(ctx->out, strdup(cfg->output_filename), cfg->with_semaphore);
|
||||
char *fname = strdup(cfg->output_filename);
|
||||
if (fname == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In init_output_ctx: Not enough memory for output filename.\n");
|
||||
ret = init_write(ctx->out, fname, cfg->with_semaphore);
|
||||
check_ret(cfg->output_filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,9 @@ void call_function_if_match(unsigned char *line, struct word_list *list, void (*
|
||||
'{', '|', '}', '~', '\0'};
|
||||
|
||||
unsigned char *line_token = strdup(line);
|
||||
if (line_token == NULL)
|
||||
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In call_function_if_match: Not enough memory for line copy.\n");
|
||||
unsigned char *c = strtok(line_token, delim);
|
||||
|
||||
if (c != NULL)
|
||||
@@ -127,6 +130,9 @@ void telx_correct_case(char *sub_line)
|
||||
'{', '|', '}', '~', '\0'};
|
||||
|
||||
char *line = strdup(((char *)sub_line));
|
||||
if (line == NULL)
|
||||
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In telx_correct_case: Not enough memory for line copy.\n");
|
||||
char *oline = (char *)sub_line;
|
||||
char *c = strtok(line, delim);
|
||||
if (c == NULL)
|
||||
|
||||
@@ -19,6 +19,9 @@ static int set_string(void *var, char *val)
|
||||
return -1;
|
||||
|
||||
val1 = strdup(val);
|
||||
if (val1 == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In set_string: Not enough memory for string copy.\n");
|
||||
*p = val1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,16 @@ struct lib_hardsubx_ctx *_init_hardsubx(struct ccx_s_options *options)
|
||||
|
||||
ctx->tess_handle = TessBaseAPICreate();
|
||||
char *pars_vec = strdup("debug_file");
|
||||
if (pars_vec == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In _init_hardsubx: Not enough memory for pars_vec.\n");
|
||||
char *pars_values = strdup("/dev/null");
|
||||
if (pars_values == NULL)
|
||||
{
|
||||
free(pars_vec);
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In _init_hardsubx: Not enough memory for pars_values.\n");
|
||||
}
|
||||
char *tessdata_path = NULL;
|
||||
|
||||
char *lang = (char *)options->ocrlang;
|
||||
|
||||
@@ -227,6 +227,9 @@ void hardsubx_process_frames_linear(struct lib_hardsubx_ctx *ctx, struct encoder
|
||||
if (subtitle_text)
|
||||
{
|
||||
prev_subtitle_text = strdup(subtitle_text);
|
||||
if (prev_subtitle_text == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In hardsubx_process_frames_linear: Not enough memory for subtitle text.\n");
|
||||
prev_sub_encoded = 0;
|
||||
}
|
||||
}
|
||||
@@ -251,6 +254,9 @@ void hardsubx_process_frames_linear(struct lib_hardsubx_ctx *ctx, struct encoder
|
||||
prev_begin_time = prev_end_time + 1;
|
||||
prev_end_time = convert_pts_to_ms(ctx->packet.pts, ctx->format_ctx->streams[ctx->video_stream_id]->time_base);
|
||||
prev_subtitle_text = strdup(subtitle_text);
|
||||
if (prev_subtitle_text == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In hardsubx_process_frames_linear: Not enough memory for subtitle text.\n");
|
||||
prev_sub_encoded = 0;
|
||||
}
|
||||
prev_packet_pts = ctx->packet.pts;
|
||||
@@ -514,6 +520,9 @@ void process_hardsubx_linear_frames_and_normal_subs(struct lib_hardsubx_ctx *har
|
||||
if (subtitle_text_hard)
|
||||
{
|
||||
prev_subtitle_text_hard = strdup(subtitle_text_hard);
|
||||
if (prev_subtitle_text_hard == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In process_hardsubx_linear_frames_and_normal_subs: Not enough memory for subtitle text.\n");
|
||||
prev_sub_encoded_hard = 0;
|
||||
}
|
||||
}
|
||||
@@ -525,6 +534,9 @@ void process_hardsubx_linear_frames_and_normal_subs(struct lib_hardsubx_ctx *har
|
||||
prev_begin_time_hard = prev_end_time_hard + 1;
|
||||
prev_end_time_hard = convert_pts_to_ms(hard_ctx->packet.pts, hard_ctx->format_ctx->streams[hard_ctx->video_stream_id]->time_base);
|
||||
prev_subtitle_text_hard = strdup(subtitle_text_hard);
|
||||
if (prev_subtitle_text_hard == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In process_hardsubx_linear_frames_and_normal_subs: Not enough memory for subtitle text.\n");
|
||||
prev_sub_encoded_hard = 0;
|
||||
}
|
||||
prev_packet_pts_hard = hard_ctx->packet.pts;
|
||||
|
||||
@@ -519,6 +519,9 @@ static char *ocr_single_line(struct ocrCtx *ctx, PIX *line_pix)
|
||||
{
|
||||
text = strdup(tess_text);
|
||||
TessDeleteText(tess_text);
|
||||
if (text == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In ocr_single_line: Not enough memory for OCR text.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ int init_write(struct ccx_s_write *wb, char *filename, int with_semaphore)
|
||||
wb->temporarily_closed = 0;
|
||||
wb->filename = filename;
|
||||
wb->original_filename = strdup(filename);
|
||||
if (wb->original_filename == NULL)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY,
|
||||
"In init_write: Not enough memory for original filename.\n");
|
||||
|
||||
wb->with_semaphore = with_semaphore;
|
||||
wb->append_mode = ccx_options.enc_cfg.append_mode;
|
||||
|
||||
@@ -27,39 +27,39 @@ uint64_t last_pts = 0; // PTS of last PES packet (debug purposes)
|
||||
// Descriptions for ts ccx_stream_type
|
||||
const char *desc[256];
|
||||
|
||||
char *get_buffer_type_str(struct cap_info *cinfo)
|
||||
const char *get_buffer_type_str(struct cap_info *cinfo)
|
||||
{
|
||||
if (cinfo->stream == CCX_STREAM_TYPE_VIDEO_MPEG2)
|
||||
{
|
||||
return strdup("MPG");
|
||||
return "MPG";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_VIDEO_H264)
|
||||
{
|
||||
return strdup("H.264");
|
||||
return "H.264";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_VIDEO_HEVC)
|
||||
{
|
||||
return strdup("HEVC");
|
||||
return "HEVC";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cinfo->codec == CCX_CODEC_ISDB_CC)
|
||||
{
|
||||
return strdup("ISDB CC subtitle");
|
||||
return "ISDB CC subtitle";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cinfo->codec == CCX_CODEC_DVB)
|
||||
{
|
||||
return strdup("DVB subtitle");
|
||||
return "DVB subtitle";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_UNKNOWNSTREAM && ccx_options.hauppauge_mode)
|
||||
{
|
||||
return strdup("Hauppage");
|
||||
return "Hauppage";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cinfo->codec == CCX_CODEC_TELETEXT)
|
||||
{
|
||||
return strdup("Teletext");
|
||||
return "Teletext";
|
||||
}
|
||||
else if (cinfo->stream == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cinfo->codec == CCX_CODEC_ATSC_CC)
|
||||
{
|
||||
return strdup("CC in private MPEG packet");
|
||||
return "CC in private MPEG packet";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user