diff --git a/makefile b/makefile index 852e043..94d4ed8 100644 --- a/makefile +++ b/makefile @@ -5,6 +5,7 @@ OPTIMIZED_SOME=-O3 OPTIMIZED_MORE=-Ofast -march=native -funit-at-a-time -flto # binary will not be compatible with other computers, but may be much faster DEBUG=-g STD=-std=c99 # maybe consider moving to c11 and using safer string handling +SECURITY=-fstack-protector-strong # detect stack buffer overflows at runtime # Dependencies for WebkitGTK4/GTK3 SRC_3=rosenrot3.c @@ -38,11 +39,11 @@ USER_CACHE_DIR=/home/`whoami`/.cache/rosenrot RUNTIME_FILES_DIR=/opt/rosenrot/ build: $(SRC_4) $(PLUGINS) $(CONFIG) constants user_cache - $(CC) $(STD) $(WARNINGS) $(DEPRECATION_FLAGS) $(OPTIMIZED_MORE) $(DEBUG) $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) + $(CC) $(STD) $(WARNINGS) $(SECURITY) $(DEPRECATION_FLAGS) $(OPTIMIZED_MORE) $(DEBUG) $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) @echo build3: $(SRC_3) $(PLUGINS) $(CONFIG) constants user_cache - $(CC) $(STD) $(WARNINGS) $(OPTIMIZED_MORE) $(DEBUG) $(INCS_3) $(PLUGINS) $(SRC_3) -o rosenrot $(LIBS_3) $(ADBLOCK) + $(CC) $(STD) $(WARNINGS) $(SECURITY) $(OPTIMIZED_MORE) $(DEBUG) $(INCS_3) $(PLUGINS) $(SRC_3) -o rosenrot $(LIBS_3) $(ADBLOCK) @echo format: $(SRC_3) $(SRC_4) $(PLUGINS) @@ -65,8 +66,8 @@ uninstall: rm $(USER_CACHE_DIR) clean: - rm rosenrot - rm $(USER_CACHE_DIR) + rm -f rosenrot + rm -rf $(USER_CACHE_DIR) constants: @echo @@ -102,11 +103,11 @@ lint: fast: $(SRC) $(PLUGINS) $(CONFIG) rm -f *.gcda GIO_MODULE_DIR=/usr/lib/x86_64-linux-gnu/gio/modules/ - $(CC) $(WARNINGS) $(OPTIMIZED_MORE) -fprofile-generate $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) + $(CC) $(WARNINGS) $(SECURITY) $(OPTIMIZED_MORE) -fprofile-generate $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) @echo "Now use the browser for a while to gather some profiling data" sleep 2 ./rosenrot - $(CC) $(WARNINGS) $(OPTIMIZED_MORE) -fprofile-use $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) + $(CC) $(WARNINGS) $(SECURITY) $(OPTIMIZED_MORE) -fprofile-use $(INCS_4) $(PLUGINS) $(SRC_4) -o rosenrot $(LIBS_4) $(ADBLOCK) rm -f *.gcda inspect: rosenrot diff --git a/plugins/libre_redirect/libre_redirect.c b/plugins/libre_redirect/libre_redirect.c index 22c28e3..08f836a 100644 --- a/plugins/libre_redirect/libre_redirect.c +++ b/plugins/libre_redirect/libre_redirect.c @@ -66,7 +66,8 @@ int libre_redirect(const char* uri, char* output) fprintf(stderr, "Unreachable state\n"); } } - strcpy(output, uri); + // Use snprintf instead of strcpy for safety + snprintf(output, len_output, "%s", uri); } int utm_check = str_destructively_omit_from(output, "?utm"); diff --git a/plugins/readability/readability.c b/plugins/readability/readability.c index 4bab3bd..13670ce 100644 --- a/plugins/readability/readability.c +++ b/plugins/readability/readability.c @@ -15,6 +15,13 @@ void read_readability_js(char* string) int i = 0; int c; while ((c = fgetc(fp)) != EOF) { + if (i >= READABILITY_N) { + fprintf(stderr, "readability.js file is too large (exceeds %d bytes)\n", READABILITY_N); + fprintf(stderr, "Consider increasing READABILITY_N or running recompute_READABILITY_N.sh\n"); + fclose(fp); + string[0] = '\0'; + return; + } string[i++] = c; } string[i] = '\0'; diff --git a/plugins/shortcuts/shortcuts.c b/plugins/shortcuts/shortcuts.c index f0e4e48..ec7acbd 100644 --- a/plugins/shortcuts/shortcuts.c +++ b/plugins/shortcuts/shortcuts.c @@ -62,7 +62,8 @@ int shortcut_expand(const char* uri, char* output) fprintf(stderr, "Unreachable state\n"); } } - strcpy(output, uri); + // Use snprintf instead of strcpy for safety + snprintf(output, len_output, "%s", uri); } if (DEBUG) printf("No match found\n\n"); return 0; diff --git a/plugins/strings/strings.c b/plugins/strings/strings.c index c95f872..632463b 100644 --- a/plugins/strings/strings.c +++ b/plugins/strings/strings.c @@ -49,7 +49,8 @@ int str_replace_start(const char* string, const char* target, const char* replac return 2; // success } else { if (DEBUG) printf("Did not find match.\n"); - strcpy(output, string); + // Use snprintf instead of strcpy for safety + snprintf(output, l4, "%s", string); } return 0; diff --git a/plugins/strings/strings.h b/plugins/strings/strings.h index 6809828..db256f9 100644 --- a/plugins/strings/strings.h +++ b/plugins/strings/strings.h @@ -2,4 +2,4 @@ void str_init(char* str, int n); int str_replace_start(const char* string, const char* target, const char* replacement, char* output); -int str_destructively_omit_from(const char* input, const char* from); +int str_destructively_omit_from(char* input, const char* from); diff --git a/plugins/style/style.c b/plugins/style/style.c index 2197d38..1ac7b3f 100644 --- a/plugins/style/style.c +++ b/plugins/style/style.c @@ -14,6 +14,13 @@ void read_style_js(char* string) int i = 0; int c; while ((c = fgetc(fp)) != EOF) { + if (i >= STYLE_N) { + fprintf(stderr, "style.js file is too large (exceeds %d bytes)\n", STYLE_N); + fprintf(stderr, "Consider increasing STYLE_N or running recompute_STYLE_N.sh\n"); + fclose(fp); + string[0] = '\0'; + return; + } string[i++] = c; } string[i] = '\0'; diff --git a/rosenrot3.c b/rosenrot3.c index 87395ed..ceef82f 100644 --- a/rosenrot3.c +++ b/rosenrot3.c @@ -48,7 +48,7 @@ void load_uri(WebKitWebView* view, const char* uri) bool has_common_domain_extension = (strstr(uri, ".com") || strstr(uri, ".org")); if (has_common_domain_extension){ char tmp[strlen("https://") + strlen(uri) + 1]; - snprintf(tmp, sizeof(tmp) + 1, "https://%s", uri); + snprintf(tmp, sizeof(tmp), "https://%s", uri); webkit_web_view_load_uri(view, tmp); return; } @@ -84,8 +84,14 @@ void set_custom_style(WebKitWebView* view) { if (custom_style_enabled) { char* style_js = malloc(STYLE_N + 1); + if (style_js == NULL) { + fprintf(stderr, "Failed to allocate memory for style_js\n"); + return; + } read_style_js(style_js); - webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); + if (style_js != NULL) { + webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); + } free(style_js); } } @@ -347,8 +353,14 @@ int handle_shortcut(func id, GtkNotebook* notebook) case prettify: { if (READABILITY_ENABLED) { char* readability_js = malloc(READABILITY_N + 1); + if (readability_js == NULL) { + fprintf(stderr, "Failed to allocate memory for readability_js\n"); + break; + } read_readability_js(readability_js); - webkit_web_view_evaluate_javascript(view, readability_js, -1, NULL, "rosenrot-readability-plugin", NULL, NULL, NULL); + if (readability_js != NULL) { + webkit_web_view_evaluate_javascript(view, readability_js, -1, NULL, "rosenrot-readability-plugin", NULL, NULL, NULL); + } free(readability_js); } break; diff --git a/rosenrot4.c b/rosenrot4.c index 40e8db8..7473f17 100644 --- a/rosenrot4.c +++ b/rosenrot4.c @@ -52,7 +52,7 @@ void load_uri(WebKitWebView* view, const char* uri) bool has_common_domain_extension = (strstr(uri, ".com") || strstr(uri, ".org")); if (has_common_domain_extension){ char tmp[strlen("https://") + strlen(uri) + 1]; - snprintf(tmp, sizeof(tmp) + 1, "https://%s", uri); + snprintf(tmp, sizeof(tmp), "https://%s", uri); webkit_web_view_load_uri(view, tmp); return; } @@ -88,8 +88,14 @@ void set_custom_style(WebKitWebView* view) { if (custom_style_enabled) { char* style_js = malloc(STYLE_N + 1); + if (style_js == NULL) { + fprintf(stderr, "Failed to allocate memory for style_js\n"); + return; + } read_style_js(style_js); - webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); + if (style_js != NULL) { + webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); + } free(style_js); } } @@ -262,7 +268,7 @@ void handle_signal_bar_press_enter(GtkEntry* self, GtkNotebook* notebook) /* con case _FILTER: { const char* js_template = "filterByKeyword(\"%s\")"; char js_command[strlen(js_template) + strlen(bar_line_text) + 2]; - snprintf(js_command, sizeof(js_command) + 1, js_template, bar_line_text); + snprintf(js_command, sizeof(js_command), js_template, bar_line_text); webkit_web_view_evaluate_javascript(view, js_command, -1, NULL, "rosenrot-filter-plugin", NULL, NULL, NULL); gtk_widget_set_visible(GTK_WIDGET(bar.widget), 0); @@ -390,8 +396,14 @@ int handle_shortcut(func id) case prettify: { if (READABILITY_ENABLED) { char* readability_js = malloc(READABILITY_N + 1); + if (readability_js == NULL) { + fprintf(stderr, "Failed to allocate memory for readability_js\n"); + break; + } read_readability_js(readability_js); - webkit_web_view_evaluate_javascript(view, readability_js, -1, NULL, "rosenrot-readability-plugin", NULL, NULL, NULL); + if (readability_js != NULL) { + webkit_web_view_evaluate_javascript(view, readability_js, -1, NULL, "rosenrot-readability-plugin", NULL, NULL, NULL); + } free(readability_js); } break; @@ -413,7 +425,7 @@ int handle_shortcut(func id) const char* uri = webkit_web_view_get_uri(view); const char* brave_command = "brave-browser --app=%s --new-window --start-fullscreen &"; char cmd[strlen(brave_command) + strlen(uri) + 2]; - snprintf(cmd, sizeof(cmd) + 1, brave_command, uri); + snprintf(cmd, sizeof(cmd), brave_command, uri); if(system(cmd) == -1) printf("Error opening in brave browser"); break; } @@ -428,14 +440,14 @@ static int handle_signal_keypress(void* self, int keyval, int keycode, GdkModifierType state, void* controller) { - if (1) { + if (0) { printf("New keypress\n"); printf("Keypress state: %d\n", state); printf("Keypress value: %d\n", keyval); } for (int i = 0; i < sizeof(shortcut) / sizeof(shortcut[0]); i++) { if ((state & shortcut[i].mod || shortcut[i].mod == 0x0) && keyval == shortcut[i].key) { - printf("New shortcut, with id: %d\n", shortcut[i].id); + return handle_shortcut(shortcut[i].id); } }