fix: improvements allocation safety and string processing

This commit is contained in:
frosty 2026-08-12 15:40:41 -04:00
commit 10d44e7ff5
No known key found for this signature in database
GPG key ID: 32DCAC76C4388DBF
5 changed files with 87 additions and 166 deletions

View file

@ -3,6 +3,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
static char *trim(char *value) {
while (*value == ' ' || *value == '\t')
value++;
char *end = value + strlen(value);
while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
end--;
*end = '\0';
return value;
}
int load_config(const char *filename, Config *config) { int load_config(const char *filename, Config *config) {
FILE *file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if (!file) { if (!file) {
@ -33,51 +44,31 @@ int load_config(const char *filename, Config *config) {
char *delimiter = strchr(line, '='); char *delimiter = strchr(line, '=');
if (delimiter) { if (delimiter) {
*delimiter = '\0'; *delimiter = '\0';
char *key = line; char *key = trim(line);
char *value = delimiter + 1; char *value = trim(delimiter + 1);
while (*key == ' ' || *key == '\t') char *value_end = value + strlen(value);
key++; while (value_end > value &&
while (*value == ' ' || *value == '\t') (value_end[-1] == '"' || value_end[-1] == '\''))
value++; *--value_end = '\0';
char *key_end = key + strlen(key) - 1;
while (key_end > key && (*key_end == ' ' || *key_end == '\t')) {
*key_end = '\0';
key_end--;
}
char *value_end = value + strlen(value) - 1;
while (value_end > value && (*value_end == ' ' || *value_end == '\t' ||
*value_end == '"' || *value_end == '\'')) {
*value_end = '\0';
value_end--;
}
while (*value == ' ' || *value == '\t')
value++;
while (*value == '"' || *value == '\'') while (*value == '"' || *value == '\'')
value++; value++;
if (strcmp(section, "server") == 0) { if (strcmp(section, "server") == 0) {
if (strcmp(key, "host") == 0) { if (strcmp(key, "host") == 0) {
strncpy(config->host, value, sizeof(config->host) - 1); snprintf(config->host, sizeof(config->host), "%s", value);
config->host[sizeof(config->host) - 1] = '\0';
} else if (strcmp(key, "port") == 0) { } else if (strcmp(key, "port") == 0) {
config->port = atoi(value); config->port = atoi(value);
} else if (strcmp(key, "locale") == 0) { } else if (strcmp(key, "locale") == 0) {
strncpy(config->default_locale, value, snprintf(config->default_locale, sizeof(config->default_locale), "%s",
sizeof(config->default_locale) - 1); value);
config->default_locale[sizeof(config->default_locale) - 1] = '\0';
} }
} else if (strcmp(section, "proxy") == 0) { } else if (strcmp(section, "proxy") == 0) {
if (strcmp(key, "proxy") == 0) { if (strcmp(key, "proxy") == 0) {
strncpy(config->proxy, value, sizeof(config->proxy) - 1); snprintf(config->proxy, sizeof(config->proxy), "%s", value);
config->proxy[sizeof(config->proxy) - 1] = '\0';
} else if (strcmp(key, "list_file") == 0) { } else if (strcmp(key, "list_file") == 0) {
strncpy(config->proxy_list_file, value, snprintf(config->proxy_list_file, sizeof(config->proxy_list_file),
sizeof(config->proxy_list_file) - 1); "%s", value);
config->proxy_list_file[sizeof(config->proxy_list_file) - 1] = '\0';
} else if (strcmp(key, "max_retries") == 0) { } else if (strcmp(key, "max_retries") == 0) {
config->max_proxy_retries = atoi(value); config->max_proxy_retries = atoi(value);
} else if (strcmp(key, "randomize_username") == 0) { } else if (strcmp(key, "randomize_username") == 0) {
@ -87,8 +78,7 @@ int load_config(const char *filename, Config *config) {
} }
} else if (strcmp(section, "cache") == 0) { } else if (strcmp(section, "cache") == 0) {
if (strcmp(key, "dir") == 0) { if (strcmp(key, "dir") == 0) {
strncpy(config->cache_dir, value, sizeof(config->cache_dir) - 1); snprintf(config->cache_dir, sizeof(config->cache_dir), "%s", value);
config->cache_dir[sizeof(config->cache_dir) - 1] = '\0';
} else if (strcmp(key, "ttl_search") == 0) { } else if (strcmp(key, "ttl_search") == 0) {
config->cache_ttl_search = atoi(value); config->cache_ttl_search = atoi(value);
} else if (strcmp(key, "ttl_infobox") == 0) { } else if (strcmp(key, "ttl_infobox") == 0) {
@ -98,12 +88,10 @@ int load_config(const char *filename, Config *config) {
} }
} else if (strcmp(section, "engines") == 0) { } else if (strcmp(section, "engines") == 0) {
if (strcmp(key, "engines") == 0) { if (strcmp(key, "engines") == 0) {
strncpy(config->engines, value, sizeof(config->engines) - 1); snprintf(config->engines, sizeof(config->engines), "%s", value);
config->engines[sizeof(config->engines) - 1] = '\0';
} else if (strcmp(key, "yacy_instance") == 0) { } else if (strcmp(key, "yacy_instance") == 0) {
strncpy(config->yacy_instance, value, snprintf(config->yacy_instance, sizeof(config->yacy_instance), "%s",
sizeof(config->yacy_instance) - 1); value);
config->yacy_instance[sizeof(config->yacy_instance) - 1] = '\0';
} }
} else if (strcmp(section, "rate_limit") == 0) { } else if (strcmp(section, "rate_limit") == 0) {
if (strcmp(key, "search_requests") == 0) { if (strcmp(key, "search_requests") == 0) {

View file

@ -251,22 +251,20 @@ static void *infobox_thread_func(void *arg) {
return NULL; return NULL;
} }
static int add_infobox_to_collection(InfoBox *infobox, char ****collection, static int add_infobox_to_collection(InfoBox *infobox,
int **inner_counts, int current_count) { StringMatrix *collection) {
const char *values[INFOBOX_FIELD_COUNT] = { const char *values[INFOBOX_FIELD_COUNT] = {
infobox->title, infobox->thumbnail_url, infobox->extract, infobox->title, infobox->thumbnail_url, infobox->extract,
infobox->url, infobox->url, infobox->url, infobox->url,
}; };
return append_string_row(collection, inner_counts, current_count, values, return string_matrix_append(collection, values, INFOBOX_FIELD_COUNT);
INFOBOX_FIELD_COUNT);
} }
static int add_warning_to_collection(const char *engine_name, static int add_warning_to_collection(const char *engine_name,
const char *warning_message, const char *warning_message,
char ****collection, int **inner_counts, StringMatrix *collection) {
int current_count) {
const char *values[] = {engine_name, warning_message}; const char *values[] = {engine_name, warning_message};
return append_string_row(collection, inner_counts, current_count, values, 2); return string_matrix_append(collection, values, 2);
} }
static void free_user_engine_list(char **user_engines, int user_engine_count) { static void free_user_engine_list(char **user_engines, int user_engine_count) {
@ -587,15 +585,14 @@ int results_handler(UrlParams *params) {
} }
if (filter_engine_count > 1) { if (filter_engine_count > 1) {
char ***filter_matrix = NULL; StringMatrix filter_matrix;
int *filter_inner_counts = NULL; string_matrix_init(&filter_matrix);
int filter_count = 0;
char *all_href = build_search_href(raw_query, "all", 1); char *all_href = build_search_href(raw_query, "all", 1);
const char *all_values[LINK_FIELD_COUNT] = {
filter_count = add_link_to_collection(
all_href, "All", all_href, "All",
selected_engine ? "engine-filter" : "engine-filter active", selected_engine ? "engine-filter" : "engine-filter active"};
&filter_matrix, &filter_inner_counts, filter_count);
string_matrix_append(&filter_matrix, all_values, LINK_FIELD_COUNT);
free(all_href); free(all_href);
for (int i = 0; i < ENGINE_COUNT; i++) { for (int i = 0; i < ENGINE_COUNT; i++) {
@ -611,17 +608,18 @@ int results_handler(UrlParams *params) {
? "engine-filter active" ? "engine-filter active"
: "engine-filter"; : "engine-filter";
filter_count = add_link_to_collection( const char *filter_values[LINK_FIELD_COUNT] = {
filter_href, ENGINE_REGISTRY[i].name, filter_class, &filter_matrix, filter_href, ENGINE_REGISTRY[i].name, filter_class};
&filter_inner_counts, filter_count); string_matrix_append(&filter_matrix, filter_values, LINK_FIELD_COUNT);
free(filter_href); free(filter_href);
} }
if (filter_count > 0) { if (filter_matrix.count > 0) {
context_set_array_of_arrays(&ctx, "engine_filters", filter_matrix, context_set_array_of_arrays(&ctx, "engine_filters", filter_matrix.rows,
filter_count, filter_inner_counts); filter_matrix.count,
free_string_matrix(filter_matrix, filter_inner_counts, filter_count); filter_matrix.field_counts);
} }
string_matrix_free(&filter_matrix);
} }
if (page == 1) { if (page == 1) {
@ -673,25 +671,23 @@ int results_handler(UrlParams *params) {
return 0; return 0;
} }
char ***infobox_matrix = NULL; StringMatrix infobox_matrix;
int *infobox_inner_counts = NULL; string_matrix_init(&infobox_matrix);
int infobox_count = 0;
if (page == 1) { if (page == 1) {
for (int i = 0; i < HANDLER_COUNT; i++) { for (int i = 0; i < HANDLER_COUNT; i++) {
if (infobox_data[i].success) { if (infobox_data[i].success) {
infobox_count = add_infobox_to_collection(&infobox_data[i].result, &infobox_matrix);
add_infobox_to_collection(&infobox_data[i].result, &infobox_matrix,
&infobox_inner_counts, infobox_count);
} }
} }
} }
if (infobox_count > 0) { if (infobox_matrix.count > 0) {
context_set_array_of_arrays(&ctx, "infoboxes", infobox_matrix, context_set_array_of_arrays(&ctx, "infoboxes", infobox_matrix.rows,
infobox_count, infobox_inner_counts); infobox_matrix.count,
free_string_matrix(infobox_matrix, infobox_inner_counts, infobox_count); infobox_matrix.field_counts);
} }
string_matrix_free(&infobox_matrix);
int warning_count = 0; int warning_count = 0;
for (int i = 0; i < enabled_engine_count; i++) { for (int i = 0; i < enabled_engine_count; i++) {
@ -700,26 +696,25 @@ int results_handler(UrlParams *params) {
} }
if (warning_count > 0) { if (warning_count > 0) {
char ***warning_matrix = NULL; StringMatrix warning_matrix;
int *warning_inner_counts = NULL; string_matrix_init(&warning_matrix);
int warning_index = 0;
for (int i = 0; i < enabled_engine_count; i++) { for (int i = 0; i < enabled_engine_count; i++) {
const char *warning_message = warning_message_for_job(&jobs[i], locale); const char *warning_message = warning_message_for_job(&jobs[i], locale);
if (!warning_message) if (!warning_message)
continue; continue;
warning_index = add_warning_to_collection( add_warning_to_collection(jobs[i].engine->name, warning_message,
jobs[i].engine->name, warning_message, &warning_matrix, &warning_matrix);
&warning_inner_counts, warning_index);
} }
if (warning_index > 0) { if (warning_matrix.count > 0) {
context_set_array_of_arrays(&ctx, "engine_warnings", warning_matrix, context_set_array_of_arrays(&ctx, "engine_warnings", warning_matrix.rows,
warning_index, warning_inner_counts); warning_matrix.count,
warning_matrix.field_counts);
} }
free_string_matrix(warning_matrix, warning_inner_counts, warning_index); string_matrix_free(&warning_matrix);
} }
int total_results = 0; int total_results = 0;

View file

@ -214,13 +214,17 @@ int setup_job(ScrapeJob *job, CURLM *multi_handle) {
return -1; return -1;
} }
for (char *p = encoded_query + strlen(encoded_query) - 3; p >= encoded_query; char *read = encoded_query;
p--) { char *write = encoded_query;
if (p[0] == '%' && p[1] == '2' && p[2] == '0') { while (*read) {
*p = '+'; if (read[0] == '%' && read[1] == '2' && read[2] == '0') {
memmove(p + 1, p + 3, strlen(p + 3) + 1); *write++ = '+';
read += 3;
} else {
*write++ = *read++;
} }
} }
*write = '\0';
char *full_url = char *full_url =
build_search_url(job->engine->base_url, job->engine->page_param, build_search_url(job->engine->base_url, job->engine->page_param,

View file

@ -14,7 +14,6 @@ static int themes_initialized = 0;
void init_themes(const char *static_path) { void init_themes(const char *static_path) {
if (themes_initialized) if (themes_initialized)
return; return;
themes_initialized = 1;
char themes_dir[512]; char themes_dir[512];
snprintf(themes_dir, sizeof(themes_dir), "%s/themes", static_path); snprintf(themes_dir, sizeof(themes_dir), "%s/themes", static_path);
@ -26,20 +25,32 @@ void init_themes(const char *static_path) {
struct dirent *entry; struct dirent *entry;
int capacity = 4; int capacity = 4;
themes_list = malloc(sizeof(char *) * capacity); themes_list = malloc(sizeof(char *) * capacity);
if (!themes_list) {
closedir(dir);
return;
}
themes_count = 0; themes_count = 0;
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
size_t len = strlen(entry->d_name); size_t len = strlen(entry->d_name);
if (len > 4 && strcmp(entry->d_name + len - 4, ".css") == 0) { if (len > 4 && strcmp(entry->d_name + len - 4, ".css") == 0) {
if (themes_count >= capacity) { if (themes_count >= capacity) {
capacity *= 2; int new_capacity = capacity * 2;
themes_list = realloc(themes_list, sizeof(char *) * capacity); char **new_list = realloc(themes_list, sizeof(char *) * new_capacity);
if (!new_list)
break;
themes_list = new_list;
capacity = new_capacity;
} }
themes_list[themes_count] = strndup(entry->d_name, len - 4); char *theme = strndup(entry->d_name, len - 4);
if (!theme)
break;
themes_list[themes_count] = theme;
themes_count++; themes_count++;
} }
} }
closedir(dir); closedir(dir);
themes_initialized = 1;
for (int i = 0; i < themes_count; i++) { for (int i = 0; i < themes_count; i++) {
for (int j = i + 1; j < themes_count; j++) { for (int j = i + 1; j < themes_count; j++) {
@ -206,50 +217,6 @@ int user_engines_contains(const char *engine_id, char **ids, int count) {
return 0; return 0;
} }
int append_string_row(char ****matrix, int **inner_counts, int row_count,
const char *const *values, int field_count) {
if (!matrix || !inner_counts || !values || field_count <= 0)
return row_count;
char **row = calloc((size_t)field_count, sizeof(*row));
if (!row)
return row_count;
for (int i = 0; i < field_count; i++) {
row[i] = strdup(values[i] ? values[i] : "");
if (!row[i]) {
for (int j = 0; j < i; j++)
free(row[j]);
free(row);
return row_count;
}
}
char ***new_matrix = malloc(sizeof(*new_matrix) * (row_count + 1));
int *new_counts = malloc(sizeof(*new_counts) * (row_count + 1));
if (!new_matrix || !new_counts) {
free(new_matrix);
free(new_counts);
for (int i = 0; i < field_count; i++)
free(row[i]);
free(row);
return row_count;
}
if (row_count > 0) {
memcpy(new_matrix, *matrix, sizeof(*new_matrix) * row_count);
memcpy(new_counts, *inner_counts, sizeof(*new_counts) * row_count);
}
new_matrix[row_count] = row;
new_counts[row_count] = field_count;
free(*matrix);
free(*inner_counts);
*matrix = new_matrix;
*inner_counts = new_counts;
return row_count + 1;
}
void free_string_matrix(char ***matrix, int *inner_counts, int row_count) { void free_string_matrix(char ***matrix, int *inner_counts, int row_count) {
if (matrix) { if (matrix) {
for (int i = 0; i < row_count; i++) { for (int i = 0; i < row_count; i++) {
@ -324,31 +291,6 @@ void string_matrix_free(StringMatrix *matrix) {
*matrix = (StringMatrix){0}; *matrix = (StringMatrix){0};
} }
int add_link_to_collection(const char *href, const char *label,
const char *class_name, char ****collection,
int **inner_counts, int current_count) {
const char *values[LINK_FIELD_COUNT] = {href, label, class_name};
return append_string_row(collection, inner_counts, current_count, values,
LINK_FIELD_COUNT);
}
int build_pagination(int page, char *(*href_builder)(int page, void *data),
void *data, char ****out_matrix, int **out_inner_counts) {
if (!out_matrix || !out_inner_counts)
return 0;
StringMatrix matrix;
if (string_matrix_build_pagination(page, href_builder, data, &matrix) != 0) {
*out_matrix = NULL;
*out_inner_counts = NULL;
return 0;
}
*out_matrix = matrix.rows;
*out_inner_counts = matrix.field_counts;
return matrix.count;
}
int string_matrix_build_pagination(int page, int string_matrix_build_pagination(int page,
char *(*href_builder)(int page, void *data), char *(*href_builder)(int page, void *data),
void *data, StringMatrix *out_matrix) { void *data, StringMatrix *out_matrix) {

View file

@ -31,8 +31,6 @@ int is_engine_id_enabled(const char *engine_id);
int get_user_engines(char ***out_ids, int *out_count); int get_user_engines(char ***out_ids, int *out_count);
int user_engines_contains(const char *engine_id, char **ids, int count); int user_engines_contains(const char *engine_id, char **ids, int count);
int append_string_row(char ****matrix, int **inner_counts, int row_count,
const char *const *values, int field_count);
void free_string_matrix(char ***matrix, int *inner_counts, int row_count); void free_string_matrix(char ***matrix, int *inner_counts, int row_count);
void string_matrix_init(StringMatrix *matrix); void string_matrix_init(StringMatrix *matrix);
@ -40,12 +38,6 @@ int string_matrix_append(StringMatrix *matrix, const char *const *values,
int field_count); int field_count);
void string_matrix_free(StringMatrix *matrix); void string_matrix_free(StringMatrix *matrix);
int add_link_to_collection(const char *href, const char *label,
const char *class_name, char ****collection,
int **inner_counts, int current_count);
int build_pagination(int page, char *(*href_builder)(int page, void *data),
void *data, char ****out_matrix, int **out_inner_counts);
int string_matrix_build_pagination(int page, int string_matrix_build_pagination(int page,
char *(*href_builder)(int page, void *data), char *(*href_builder)(int page, void *data),
void *data, StringMatrix *out_matrix); void *data, StringMatrix *out_matrix);