From 529e7841abc8fd58c3b51bd4857edf8f9c50c136 Mon Sep 17 00:00:00 2001 From: Andrey Skvortsov Date: Wed, 28 May 2025 01:06:52 +0300 Subject: [PATCH] process_pipeline: replace sprintf with snprintf to avoid potential buffer overflows --- src/main.c | 5 +-- src/process_pipeline.c | 80 +++++++++++++++++++++++------------------- src/process_pipeline.h | 3 +- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/main.c b/src/main.c index c67db08..90fe1f6 100644 --- a/src/main.c +++ b/src/main.c @@ -1413,9 +1413,10 @@ activate(GtkApplication *app, gpointer data) // Initialize the postprocessing gsetting to the old processor if // it was not set yet if (setting_postproc == NULL || setting_postproc[0] == '\0') { + const int size = 512; printf("Initializing postprocessor gsetting\n"); - setting_postproc = malloc(512); - if (!mp_process_find_processor(setting_postproc, "postprocess.sh")) { + setting_postproc = malloc(size); + if (!mp_process_find_processor(setting_postproc, size, "postprocess.sh")) { printf("No processor found\n"); exit(1); } diff --git a/src/process_pipeline.c b/src/process_pipeline.c index 6e389ae..50a6334 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -68,7 +68,7 @@ mp_process_find_all_processors(GtkListStore *store) } // Check for a script in XDG_CONFIG_HOME - sprintf(buffer, "%s/megapixels/postprocess.sh", g_get_user_config_dir()); + snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", g_get_user_config_dir()); if (access(buffer, F_OK) != -1) { gtk_list_store_insert(store, &iter, -1); gtk_list_store_set( @@ -76,7 +76,7 @@ mp_process_find_all_processors(GtkListStore *store) } // Check user overridden /etc/megapixels/postprocess.sh - sprintf(buffer, "%s/megapixels/postprocess.sh", SYSCONFDIR); + snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", SYSCONFDIR); if (access(buffer, F_OK) != -1) { gtk_list_store_insert(store, &iter, -1); gtk_list_store_set( @@ -84,7 +84,7 @@ mp_process_find_all_processors(GtkListStore *store) } // Check user overridden /usr/share/megapixels/postprocess.sh - sprintf(buffer, "%s/megapixels/postprocess.sh", DATADIR); + snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", DATADIR); if (access(buffer, F_OK) != -1) { gtk_list_store_insert(store, &iter, -1); gtk_list_store_set( @@ -94,7 +94,7 @@ mp_process_find_all_processors(GtkListStore *store) // Find extra packaged postprocessor scripts // These should be packaged in // /usr/share/megapixels/postprocessor.d/executable - sprintf(buffer, "%s/megapixels/postprocessor.d", DATADIR); + snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocessor.d", DATADIR); DIR *d; struct dirent *dir; d = opendir(buffer); @@ -103,10 +103,11 @@ mp_process_find_all_processors(GtkListStore *store) if (dir->d_name[0] == '.') { continue; } - sprintf(buffer, - "%s/megapixels/postprocessor.d/%s", - DATADIR, - dir->d_name); + snprintf(buffer, + sizeof(buffer), + "%s/megapixels/postprocessor.d/%s", + DATADIR, + dir->d_name); gtk_list_store_insert(store, &iter, -1); gtk_list_store_set( store, &iter, 0, buffer, 1, dir->d_name, -1); @@ -116,32 +117,32 @@ mp_process_find_all_processors(GtkListStore *store) } bool -mp_process_find_processor(char *script, char *filename) +mp_process_find_processor(char *script, int size, char *filename) { // Check postprocess.sh in the current working directory - sprintf(script, "./data/%s", filename); + snprintf(script, size, "./data/%s", filename); if (access(script, F_OK) != -1) { - sprintf(script, "./data/%s", filename); + snprintf(script, size, "./data/%s", filename); printf("Found postprocessor script at %s\n", script); return true; } // Check for a script in XDG_CONFIG_HOME - sprintf(script, "%s/megapixels/%s", g_get_user_config_dir(), filename); + snprintf(script, size, "%s/megapixels/%s", g_get_user_config_dir(), filename); if (access(script, F_OK) != -1) { printf("Found postprocessor script at %s\n", script); return true; } // Check user overridden /etc/megapixels/postprocessor.sh - sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename); + snprintf(script, size, "%s/megapixels/%s", SYSCONFDIR, filename); if (access(script, F_OK) != -1) { printf("Found postprocessor script at %s\n", script); return true; } // Check packaged /usr/share/megapixels/postprocessor.sh - sprintf(script, "%s/megapixels/%s", DATADIR, filename); + snprintf(script, size, "%s/megapixels/%s", DATADIR, filename); if (access(script, F_OK) != -1) { printf("Found postprocessor script at %s\n", script); return true; @@ -161,7 +162,7 @@ static void setup_capture(void) exit(EXIT_FAILURE); } - snprintf(burst_dir, sizeof(bufst_dir), tempdir); + snprintf(burst_dir, sizeof(burst_dir), tempdir); } static void @@ -175,7 +176,7 @@ setup(MPPipeline *pipeline, const void *data) state_proc.mode_exposure = AAA_BY_V4L2_CONTROLS; state_proc.mode_focus = AAA_DISABLED; - if (!mp_process_find_processor(movie_script, "movie.sh")) { + if (!mp_process_find_processor(movie_script, sizeof(movie_script), "movie.sh")) { fprintf(stderr,"movie.sh not found, video pipeline disabled\n"); } setup_capture(); @@ -525,10 +526,11 @@ summarize() (float) time, (float) gain, state_proc.gain.value, state_proc.dgain.value, (float) 1/diopt); - sprintf(buf, "1/%s%.0f%sISO%s%.0f%sm%s%.2f", - sep, (float) (1.0/time), sep, - sep, (float) (gain*100), - sep, sep, 1/diopt); + snprintf(buf, sizeof(buf), + "1/%s%.0f%sISO%s%.0f%sm%s%.2f", + sep, (float) (1.0/time), sep, + sep, (float) (gain*100), + sep, sep, 1/diopt); /* Not sure what to do here. Looks like we need to call gtk functions from main thread. @@ -979,9 +981,10 @@ save_grw(const uint8_t *image, char *fname) fwrite(image, size, 1, outfile); char buf[1024]; buf[0] = 0; - int header = sprintf(buf+1, - "Caps: video/x-raw,format=%s,width=%d,height=%d\nSize: %d\nGRW", - format, width, height, size); + int header = snprintf(buf + 1, + sizeof(buf) - 1, + "Caps: video/x-raw,format=%s,width=%d,height=%d\nSize: %d\nGRW", + format, width, height, size); fwrite(buf, header+1, 1, outfile); fclose(outfile); } @@ -1074,7 +1077,7 @@ static void process_image_for_capture_yuv(const uint8_t *image, int count) { char fname[255]; - sprintf(fname, "%s/%d.jpg", burst_dir, count); + snprintf(fname, sizeof(fname), "%s/%d.jpg", burst_dir, count); save_jpeg(image, fname); } @@ -1234,7 +1237,7 @@ static void process_image_for_capture_bayer(const uint8_t *image, int count) { char fname[255]; - sprintf(fname, "%s/%d.dng", burst_dir, count); + snprintf(fname, sizeof(fname), "%s/%d.dng", burst_dir, count); save_dng(image, fname, count); } @@ -1287,20 +1290,23 @@ process_capture_burst(GdkTexture *thumb) format_timestamp(timestamp); if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) { - sprintf(capture_fname, - "%s/IMG%s", - g_get_user_special_dir(G_USER_DIRECTORY_PICTURES), - timestamp); + snprintf(capture_fname, + sizeof(capture_fname), + "%s/IMG%s", + g_get_user_special_dir(G_USER_DIRECTORY_PICTURES), + timestamp); } else if (getenv("XDG_PICTURES_DIR") != NULL) { - sprintf(capture_fname, - "%s/IMG%s", - getenv("XDG_PICTURES_DIR"), - timestamp); + snprintf(capture_fname, + sizeof(capture_fname), + "%s/IMG%s", + getenv("XDG_PICTURES_DIR"), + timestamp); } else { - sprintf(capture_fname, - "%s/Pictures/IMG%s", - getenv("HOME"), - timestamp); + snprintf(capture_fname, + sizeof(capture_fname), + "%s/Pictures/IMG%s", + getenv("HOME"), + timestamp); } bool save_dng = g_settings_get_boolean(settings, "save-raw"); diff --git a/src/process_pipeline.h b/src/process_pipeline.h index 6c381b7..014a87d 100644 --- a/src/process_pipeline.h +++ b/src/process_pipeline.h @@ -37,7 +37,8 @@ struct mp_process_pipeline_state { bool control_focus; }; -bool mp_process_find_processor(char *script, char *filename); + +bool mp_process_find_processor(char *script, int size, char *filename); void mp_process_find_all_processors(GtkListStore *store); void mp_process_pipeline_start();