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 <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) {
FILE *file = fopen(filename, "r");
if (!file) {
@ -33,51 +44,31 @@ int load_config(const char *filename, Config *config) {
char *delimiter = strchr(line, '=');
if (delimiter) {
*delimiter = '\0';
char *key = line;
char *value = delimiter + 1;
char *key = trim(line);
char *value = trim(delimiter + 1);
while (*key == ' ' || *key == '\t')
key++;
while (*value == ' ' || *value == '\t')
value++;
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++;
char *value_end = value + strlen(value);
while (value_end > value &&
(value_end[-1] == '"' || value_end[-1] == '\''))
*--value_end = '\0';
while (*value == '"' || *value == '\'')
value++;
if (strcmp(section, "server") == 0) {
if (strcmp(key, "host") == 0) {
strncpy(config->host, value, sizeof(config->host) - 1);
config->host[sizeof(config->host) - 1] = '\0';
snprintf(config->host, sizeof(config->host), "%s", value);
} else if (strcmp(key, "port") == 0) {
config->port = atoi(value);
} else if (strcmp(key, "locale") == 0) {
strncpy(config->default_locale, value,
sizeof(config->default_locale) - 1);
config->default_locale[sizeof(config->default_locale) - 1] = '\0';
snprintf(config->default_locale, sizeof(config->default_locale), "%s",
value);
}
} else if (strcmp(section, "proxy") == 0) {
if (strcmp(key, "proxy") == 0) {
strncpy(config->proxy, value, sizeof(config->proxy) - 1);
config->proxy[sizeof(config->proxy) - 1] = '\0';
snprintf(config->proxy, sizeof(config->proxy), "%s", value);
} else if (strcmp(key, "list_file") == 0) {
strncpy(config->proxy_list_file, value,
sizeof(config->proxy_list_file) - 1);
config->proxy_list_file[sizeof(config->proxy_list_file) - 1] = '\0';
snprintf(config->proxy_list_file, sizeof(config->proxy_list_file),
"%s", value);
} else if (strcmp(key, "max_retries") == 0) {
config->max_proxy_retries = atoi(value);
} 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) {
if (strcmp(key, "dir") == 0) {
strncpy(config->cache_dir, value, sizeof(config->cache_dir) - 1);
config->cache_dir[sizeof(config->cache_dir) - 1] = '\0';
snprintf(config->cache_dir, sizeof(config->cache_dir), "%s", value);
} else if (strcmp(key, "ttl_search") == 0) {
config->cache_ttl_search = atoi(value);
} 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) {
if (strcmp(key, "engines") == 0) {
strncpy(config->engines, value, sizeof(config->engines) - 1);
config->engines[sizeof(config->engines) - 1] = '\0';
snprintf(config->engines, sizeof(config->engines), "%s", value);
} else if (strcmp(key, "yacy_instance") == 0) {
strncpy(config->yacy_instance, value,
sizeof(config->yacy_instance) - 1);
config->yacy_instance[sizeof(config->yacy_instance) - 1] = '\0';
snprintf(config->yacy_instance, sizeof(config->yacy_instance), "%s",
value);
}
} else if (strcmp(section, "rate_limit") == 0) {
if (strcmp(key, "search_requests") == 0) {

View file

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

View file

@ -214,13 +214,17 @@ int setup_job(ScrapeJob *job, CURLM *multi_handle) {
return -1;
}
for (char *p = encoded_query + strlen(encoded_query) - 3; p >= encoded_query;
p--) {
if (p[0] == '%' && p[1] == '2' && p[2] == '0') {
*p = '+';
memmove(p + 1, p + 3, strlen(p + 3) + 1);
char *read = encoded_query;
char *write = encoded_query;
while (*read) {
if (read[0] == '%' && read[1] == '2' && read[2] == '0') {
*write++ = '+';
read += 3;
} else {
*write++ = *read++;
}
}
*write = '\0';
char *full_url =
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) {
if (themes_initialized)
return;
themes_initialized = 1;
char themes_dir[512];
snprintf(themes_dir, sizeof(themes_dir), "%s/themes", static_path);
@ -26,20 +25,32 @@ void init_themes(const char *static_path) {
struct dirent *entry;
int capacity = 4;
themes_list = malloc(sizeof(char *) * capacity);
if (!themes_list) {
closedir(dir);
return;
}
themes_count = 0;
while ((entry = readdir(dir)) != NULL) {
size_t len = strlen(entry->d_name);
if (len > 4 && strcmp(entry->d_name + len - 4, ".css") == 0) {
if (themes_count >= capacity) {
capacity *= 2;
themes_list = realloc(themes_list, sizeof(char *) * capacity);
int new_capacity = capacity * 2;
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++;
}
}
closedir(dir);
themes_initialized = 1;
for (int i = 0; i < themes_count; i++) {
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;
}
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) {
if (matrix) {
for (int i = 0; i < row_count; i++) {
@ -324,31 +291,6 @@ void string_matrix_free(StringMatrix *matrix) {
*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,
char *(*href_builder)(int page, void *data),
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 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 string_matrix_init(StringMatrix *matrix);
@ -40,12 +38,6 @@ int string_matrix_append(StringMatrix *matrix, const char *const *values,
int field_count);
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,
char *(*href_builder)(int page, void *data),
void *data, StringMatrix *out_matrix);