From 811bbb1194f2940eebffbc9b2c755c5fbae98459 Mon Sep 17 00:00:00 2001 From: Thorsten Greiner Date: Tue, 13 Jan 2026 09:03:36 +0100 Subject: [PATCH] Replace all memory allocations with safe_ versions --- include/Makefile.am | 7 +++-- include/blunder.h | 2 +- include/safe_malloc.h | 65 +++++++++++++++++++++++++++++++++++++++++ src/blunder.c | 5 ++-- src/bookup.c | 3 +- src/dbase.c | 27 ++++------------- src/evaluation_config.c | 14 ++++----- src/hashtable.c | 7 +++-- src/heap.c | 21 ++++--------- src/next.c | 27 ++++------------- src/probe.c | 3 +- src/search.c | 9 ++---- src/tree.c | 34 +++++++-------------- src/yaml.c | 26 +++++------------ 14 files changed, 120 insertions(+), 130 deletions(-) create mode 100644 include/safe_malloc.h diff --git a/include/Makefile.am b/include/Makefile.am index a7edf72..7f35614 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,9 +1,10 @@ noinst_HEADERS = amy.h bitboard.h blunder.h bookup.h commands.h dbase.h eco.h \ evaluation.h evaluation_config.h filter.h hashtable.h heap.h \ init.h inline.h learn.h magic.h mates.h movedata.h next.h \ - pgn.h probe.h random.h recog.h search.h search_io.h \ - state_machine.h swap.h test_blunder.h test_dbase.h \ - test_yaml.h time_ctl.h tree.h types.h utils.h yaml.h + pgn.h probe.h random.h recog.h safe_malloc.h search.h \ + search_io.h state_machine.h swap.h test_blunder.h \ + test_dbase.h test_yaml.h time_ctl.h tree.h types.h utils.h \ + yaml.h .PHONY: format format: diff --git a/include/blunder.h b/include/blunder.h index 4aa7427..aa1927e 100644 --- a/include/blunder.h +++ b/include/blunder.h @@ -32,8 +32,8 @@ #ifndef BLUNDER_H #define BLUNDER_H -#include "types.h" #include "dbase.h" +#include "types.h" move_t get_best_move_from_comment(char *, struct Position *, char *); void BlunderCheck(char *); diff --git a/include/safe_malloc.h b/include/safe_malloc.h new file mode 100644 index 0000000..98c074f --- /dev/null +++ b/include/safe_malloc.h @@ -0,0 +1,65 @@ +/* + + Amy - a chess playing program + + Copyright (c) 2002-2026, Thorsten Greiner + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SAFE_MALLOC_H +#define SAFE_MALLOC_H + +#include +#include + +static void *safe_malloc(size_t size) { + void *ptr = malloc(size); + if (ptr == NULL) { + perror(NULL); + exit(1); + } + return ptr; +} + +static void *safe_calloc(size_t count, size_t size) { + void *ptr = calloc(count, size); + if (ptr == NULL) { + perror(NULL); + exit(1); + } + return ptr; +} + +static void *safe_realloc(void *old_ptr, size_t size) { + void *ptr = realloc(old_ptr, size); + if (ptr == NULL) { + perror(NULL); + exit(1); + } + return ptr; +} + +#endif diff --git a/src/blunder.c b/src/blunder.c index 8da8686..8081179 100644 --- a/src/blunder.c +++ b/src/blunder.c @@ -31,10 +31,10 @@ #include "dbase.h" #include "pgn.h" +#include "safe_malloc.h" #include "search.h" #include "types.h" #include "utils.h" -#include "yaml.h" #include #include #include @@ -71,8 +71,7 @@ move_t get_best_move_from_comment(char *comment, struct Position *p, size_t len = strlen(ptr); - char *buffer = malloc(len + 1); - abort_if_allocation_failed(buffer); + char *buffer = safe_malloc(len + 1); strncpy(buffer, ptr, len + 1); diff --git a/src/bookup.c b/src/bookup.c index f2db7b2..81d999b 100644 --- a/src/bookup.c +++ b/src/bookup.c @@ -41,6 +41,7 @@ #include "eco.h" #include "pgn.h" #include "random.h" +#include "safe_malloc.h" #include "tree.h" #include "utils.h" @@ -91,7 +92,7 @@ static tree_node_t *PutBookEntry(tree_node_t *database, hash_t hk, int result, } if (entry == NULL) { - entry = calloc(1, sizeof(struct BookEntry)); + entry = safe_calloc(1, sizeof(struct BookEntry)); } if (result == 1) { diff --git a/src/dbase.c b/src/dbase.c index 33a45dc..8a26598 100644 --- a/src/dbase.c +++ b/src/dbase.c @@ -44,6 +44,7 @@ #include "magic.h" #include "mates.h" #include "recog.h" +#include "safe_malloc.h" #include "swap.h" #include "types.h" #include "utils.h" @@ -2164,7 +2165,7 @@ static void ReadEPD(struct Position *p, char *x) { * due to the use of strtok, sorry :-) */ - line = malloc(strlen(x) + 1); + line = safe_malloc(strlen(x) + 1); strcpy(line, x); x = line; @@ -2558,17 +2559,9 @@ bool IsPassed(const struct Position *p, int sq, int side) { */ struct Position *CreatePositionFromEPD(char *epd) { - struct Position *p = calloc(1, sizeof(struct Position)); - if (!p) { - Print(0, "Cannot allocate Position.\n"); - exit(1); - } + struct Position *p = safe_calloc(1, sizeof(struct Position)); p->gameLogSize = INITIAL_GAME_LOG_SIZE; - p->gameLog = calloc(p->gameLogSize, sizeof(struct GameLog)); - if (!p->gameLog) { - Print(0, "Cannot allocate GameLog.\n"); - exit(1); - } + p->gameLog = safe_calloc(p->gameLogSize, sizeof(struct GameLog)); p->actLog = p->gameLog; ReadEPD(p, epd); p->actLog->gl_IrrevCount = 0; @@ -2594,19 +2587,11 @@ struct Position *InitialPosition(void) { } struct Position *ClonePosition(struct Position *src) { - struct Position *p = calloc(1, sizeof(struct Position)); - if (!p) { - Print(0, "Cannot allocated Position.\n"); - exit(1); - } + struct Position *p = safe_calloc(1, sizeof(struct Position)); memcpy(p, src, sizeof(struct Position)); p->gameLogSize = src->gameLogSize; - p->gameLog = calloc(p->gameLogSize, sizeof(struct GameLog)); - if (!p->gameLog) { - Print(0, "Cannot allocate GameLog.\n"); - exit(1); - } + p->gameLog = safe_calloc(p->gameLogSize, sizeof(struct GameLog)); memcpy(p->gameLog, src->gameLog, sizeof(struct GameLog) * p->gameLogSize); p->actLog = p->gameLog + (src->actLog - src->gameLog); diff --git a/src/evaluation_config.c b/src/evaluation_config.c index 82c8e52..bf03171 100644 --- a/src/evaluation_config.c +++ b/src/evaluation_config.c @@ -34,6 +34,7 @@ #include "dbase.h" #include "evaluation.h" +#include "safe_malloc.h" #include "search.h" #include "utils.h" #include "yaml.h" @@ -265,8 +266,7 @@ static void set_piece_square_table(struct Node *node, char *name, static void set_array(struct Node *node, char *name, int16_t *target_array, unsigned int count) { - int *destination = malloc(sizeof(int) * count); - abort_if_allocation_failed(destination); + int *destination = safe_malloc(sizeof(int) * count); struct IntArrayLookupResult array_result = get_as_int_array(node, name, destination, count); @@ -292,7 +292,6 @@ static void configure_name(struct Node *node) { if (result.result_code == OK) { ConfigurationName = result.result; - abort_if_allocation_failed(ConfigurationName); Print(0, "Using configuration name: %s\n", ConfigurationName); } } @@ -403,8 +402,7 @@ static char *read_file(char *file_name) { size_t buf_size = page_size; size_t total_bytes_read = 0; - char *buffer = malloc(buf_size); - abort_if_allocation_failed(buffer); + char *buffer = safe_malloc(buf_size); char *ptr = buffer; @@ -419,8 +417,7 @@ static char *read_file(char *file_name) { if ((total_bytes_read + page_size) >= buf_size) { buf_size *= 2; - buffer = realloc(buffer, buf_size); - abort_if_allocation_failed(buffer); + buffer = safe_realloc(buffer, buf_size); ptr = buffer + total_bytes_read; } } @@ -429,8 +426,7 @@ static char *read_file(char *file_name) { if ((total_bytes_read + 1) >= buf_size) { buf_size += 1; - buffer = realloc(buffer, buf_size); - abort_if_allocation_failed(buffer); + buffer = safe_realloc(buffer, buf_size); } *ptr = '\0'; diff --git a/src/hashtable.c b/src/hashtable.c index e294b54..42862e3 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -38,6 +38,7 @@ #include "hashtable.h" #include "random.h" +#include "safe_malloc.h" #include "search.h" #include "utils.h" @@ -540,7 +541,7 @@ void AllocateHT(void) { HT_Size = 1 << HT_Bits; HT_Mask = HT_Size - 1; - TranspositionTable = calloc(HT_Size, sizeof(struct HTEntry)); + TranspositionTable = safe_calloc(HT_Size, sizeof(struct HTEntry)); /* Thread-local hash table - only calculate sizes and bits here...*/ L_HT_Size = 1 << L_HT_Bits; @@ -549,12 +550,12 @@ void AllocateHT(void) { PT_Size = 1 << PT_Bits; PT_Mask = PT_Size - 1; - PawnTable = calloc(PT_Size, sizeof(struct PTEntry)); + PawnTable = safe_calloc(PT_Size, sizeof(struct PTEntry)); ST_Size = 1 << ST_Bits; ST_Mask = ST_Size - 1; - ScoreTable = calloc(ST_Size, sizeof(struct STEntry)); + ScoreTable = safe_calloc(ST_Size, sizeof(struct STEntry)); Print(0, "Hashtable sizes: %d k, %d k, %d k (%d, %d, %d bits)\n", ((1 << HT_Bits) * sizeof(struct HTEntry)) / 1024, diff --git a/src/heap.c b/src/heap.c index 3fea41a..8e77f66 100644 --- a/src/heap.c +++ b/src/heap.c @@ -30,32 +30,21 @@ */ #include "heap.h" +#include "safe_malloc.h" static const int DATA_SIZE = 1024; static const int SECTION_SIZE = 32; heap_t allocate_heap(void) { - heap_t heap = (heap_t)malloc(sizeof(struct heap)); - if (heap == NULL) { - perror("Cannot allocate heap:"); - exit(1); - } - - move_t *data = (move_t *)malloc(DATA_SIZE * sizeof(move_t)); - if (data == NULL) { - perror("Cannot allocate heap:"); - exit(1); - } + heap_t heap = (heap_t)safe_malloc(sizeof(struct heap)); + + move_t *data = (move_t *)safe_malloc(DATA_SIZE * sizeof(move_t)); heap->data = data; heap->capacity = DATA_SIZE; heap_section_t sections = - (heap_section_t)malloc(SECTION_SIZE * sizeof(struct heap_section)); - if (sections == NULL) { - perror("Cannot allocate heap:"); - exit(1); - } + (heap_section_t)safe_malloc(SECTION_SIZE * sizeof(struct heap_section)); heap->sections_start = sections; heap->sections_end = sections + SECTION_SIZE; diff --git a/src/next.c b/src/next.c index 9fb9365..1703cca 100644 --- a/src/next.c +++ b/src/next.c @@ -39,6 +39,7 @@ #include "heap.h" #include "init.h" #include "inline.h" +#include "safe_malloc.h" #include "search.h" #include "swap.h" #include "utils.h" @@ -47,26 +48,12 @@ #endif struct SearchData *CreateSearchData(struct Position *p) { - struct SearchData *sd = calloc(1, sizeof(struct SearchData)); - if (!sd) { - Print(0, "Cannot allocate SearchData.\n"); - exit(1); - } + struct SearchData *sd = safe_calloc(1, sizeof(struct SearchData)); sd->position = p; - - sd->statusTable = calloc(MAX_TREE_SIZE, sizeof(struct SearchStatus)); - if (!sd->statusTable) { - Print(0, "Cannot allocate SearchStatus.\n"); - exit(1); - } + sd->statusTable = safe_calloc(MAX_TREE_SIZE, sizeof(struct SearchStatus)); sd->current = sd->statusTable; - - sd->killerTable = calloc(MAX_TREE_SIZE, sizeof(struct KillerEntry)); - if (!sd->killerTable) { - Print(0, "Cannot allocate KillerEntry.\n"); - exit(1); - } + sd->killerTable = safe_calloc(MAX_TREE_SIZE, sizeof(struct KillerEntry)); sd->killer = sd->killerTable; sd->heap = allocate_heap(); @@ -75,11 +62,7 @@ struct SearchData *CreateSearchData(struct Position *p) { sd->data_heap_size = 0; #if MP - sd->localHashTable = calloc(sizeof(struct HTEntry), L_HT_Size); - if (!sd->localHashTable) { - Print(0, "Cannot allocate thread-local hashtable.\n"); - exit(1); - } + sd->localHashTable = safe_calloc(sizeof(struct HTEntry), L_HT_Size); sd->deferred_heap = allocate_heap(); #endif diff --git a/src/probe.c b/src/probe.c index 834a988..943a681 100644 --- a/src/probe.c +++ b/src/probe.c @@ -9,6 +9,7 @@ #include "config.h" #include "dbase.h" +#include "safe_malloc.h" #include "search.h" #include "utils.h" #include @@ -68,7 +69,7 @@ void InitEGTB(char *tbpath) { TB_CRC_CHECK = 0; EGTBMenCount = IInitializeTb(tbpath); if (EGTBMenCount != 0) { - void *egtb_cache = malloc(EGTB_CACHE_SIZE); + void *egtb_cache = safe_malloc(EGTB_CACHE_SIZE); Print(0, "Found %d-men endgame table bases.\n", EGTBMenCount); FTbSetCacheSize(egtb_cache, EGTB_CACHE_SIZE); } diff --git a/src/search.c b/src/search.c index 3f827a0..f6d3af1 100644 --- a/src/search.c +++ b/src/search.c @@ -48,6 +48,7 @@ #include "probe.h" #include "random.h" #include "recog.h" +#include "safe_malloc.h" #include "search_io.h" #include "state_machine.h" #include "swap.h" @@ -1679,13 +1680,7 @@ static void StartHelpers(struct Position *p) { if (NumberOfCPUs < 2) return; - tids = calloc(NumberOfCPUs - 1, sizeof(pthread_t)); - - if (tids == NULL) { - Print(0, "Cannot allocate memory for helpers.\n"); - Print(0, "Will try to search sequential.\n"); - return; - } + tids = safe_calloc(NumberOfCPUs - 1, sizeof(pthread_t)); pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); diff --git a/src/tree.c b/src/tree.c index d612c35..50d6155 100644 --- a/src/tree.c +++ b/src/tree.c @@ -35,6 +35,7 @@ #include #include +#include "safe_malloc.h" #include "tree.h" /** Magic constant to identify trees written to disk. */ @@ -45,24 +46,12 @@ static const char *MAGIC = "ATRE"; */ static tree_node_t *allocate_node(void *key_data, size_t key_len, void *value_data, size_t value_len) { - tree_node_t *node = malloc(sizeof(tree_node_t)); - if (node == NULL) { - perror("Failed to allocate node"); - exit(1); - } + tree_node_t *node = safe_malloc(sizeof(tree_node_t)); - node->key_data = malloc(key_len); - if (node->key_data == NULL) { - perror("Failed to allocate key_data"); - exit(1); - } + node->key_data = safe_malloc(key_len); node->key_len = key_len; - node->value_data = malloc(value_len); - if (node->value_data == NULL) { - perror("Failed to allocate value_data"); - exit(1); - } + node->value_data = safe_malloc(value_len); node->value_len = value_len; memcpy(node->key_data, key_data, key_len); @@ -222,7 +211,7 @@ tree_node_t *add_node(tree_node_t *node, void *key_data, size_t key_len, int comparison = cmp_keys(key_data, key_len, node->key_data, node->key_len); if (comparison == 0) { - node->value_data = realloc(node->value_data, value_len); + node->value_data = safe_realloc(node->value_data, value_len); if (node->value_data == NULL) { perror("Failed to allocate value_data"); exit(1); @@ -257,10 +246,7 @@ static void *lookup_value_internal(tree_node_t *node, char *key_data, if (value_len != NULL) { *value_len = node->value_len; } - char *buffer = malloc(node->value_len); - if (buffer == NULL) { - return NULL; - } + char *buffer = safe_malloc(node->value_len); memcpy(buffer, node->value_data, node->value_len); return buffer; } else if (comparison < 0) { @@ -353,15 +339,15 @@ static tree_node_t *load_tree_internal(FILE *fin) { tree_node_t *node = NULL; size_t key_len; size_t value_len; - char *key_data = malloc(8); - char *value_data = malloc(256); + char *key_data = safe_malloc(8); + char *value_data = safe_malloc(256); for (;;) { key_len = read_size(fin); if (key_len == 0) break; - key_data = realloc(key_data, key_len); + key_data = safe_realloc(key_data, key_len); unsigned long amount_read = fread(key_data, key_len, 1, fin); if (amount_read != 1) break; @@ -370,7 +356,7 @@ static tree_node_t *load_tree_internal(FILE *fin) { if (value_len == 0) break; - value_data = realloc(value_data, value_len); + value_data = safe_realloc(value_data, value_len); amount_read = fread(value_data, value_len, 1, fin); if (amount_read != 1) break; diff --git a/src/yaml.c b/src/yaml.c index 80e2f19..02b1cd8 100644 --- a/src/yaml.c +++ b/src/yaml.c @@ -36,6 +36,7 @@ #include #include +#include "safe_malloc.h" #include "tree.h" #include "yaml.h" @@ -51,13 +52,6 @@ void free_yaml_node(struct Node *); void free_list_node(struct ListNode *); void free_tree_node(tree_node_t *tree); -void abort_if_allocation_failed(void *x) { - if (!x) { - perror("Cannot allocate buffer"); - exit(1); - } -} - static bool is_word_char(char c) { return isalnum(c) || c == '_' || c == '-'; } static struct Token token_from_type(TokenType type) { @@ -83,8 +77,7 @@ struct Token parse_word(struct TokenizerState *state) { length -= trailing_blanks; - char *buffer = malloc(length + 1); - abort_if_allocation_failed(buffer); + char *buffer = safe_malloc(length + 1); memcpy(buffer, begin, length); buffer[length] = '\0'; @@ -218,15 +211,13 @@ struct ListNode *parse_list(struct TokenizerState *state) { for (;;) { if (token.type == WORD) { - struct Node *value = malloc(sizeof(struct Node)); - abort_if_allocation_failed(value); + struct Node *value = safe_malloc(sizeof(struct Node)); value->type = SCALAR; value->payload = token.text; // printf("Parsed list element: %s\n", token.text); - struct ListNode *next_node = malloc(sizeof(struct ListNode)); - abort_if_allocation_failed(next_node); + struct ListNode *next_node = safe_malloc(sizeof(struct ListNode)); next_node->value = value; next_node->next = NULL; @@ -315,8 +306,7 @@ struct Node *parse_dict(struct TokenizerState *state) { // printf("Finished parsing dict.\n"); - struct Node *result = malloc(sizeof(struct Node)); - abort_if_allocation_failed(result); + struct Node *result = safe_malloc(sizeof(struct Node)); result->type = DICT; result->payload = result_dict; @@ -335,8 +325,7 @@ struct Node *parse_yaml(char *text) { struct Node *get_node(struct Node *node, char *path) { // Make a copy of path because strtok will clobber it - char *path_buffer = malloc(strlen(path) + 1); - abort_if_allocation_failed(path_buffer); + char *path_buffer = safe_malloc(strlen(path) + 1); memcpy(path_buffer, path, strlen(path) + 1); char *x = path_buffer; @@ -369,8 +358,7 @@ struct Node *get_node(struct Node *node, char *path) { } free(path_buffer); - struct Node *result = malloc(sizeof(struct Node)); - abort_if_allocation_failed(result); + struct Node *result = safe_malloc(sizeof(struct Node)); memcpy(result, ¤t_node, sizeof(struct Node)); return result;