diff --git a/.gitignore b/.gitignore index 71ec079..99b470c 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ lt-*.c /src/test_bbs /src/test_bwf /src/test_hash_dict +/src/test_ip_mask diff --git a/configure.ac b/configure.ac index d30dd8a..06510c7 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lbbs],[1.7.9]) +AC_INIT([lbbs],[1.7.10]) AC_CONFIG_SRCDIR([src/]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([m4]) diff --git a/include/log.h b/include/log.h index 2007db5..b53f401 100644 --- a/include/log.h +++ b/include/log.h @@ -18,10 +18,18 @@ enum log_level_t LOG_LEVEL_DEBUG, }; +// Enable compile-time format string checking for log_* calls (GCC / Clang) +#if defined(__GNUC__) +#define LOG_PRINTF_FORMAT_ATTR __attribute__((format(printf, 4, 5))) +#else +#define LOG_PRINTF_FORMAT_ATTR +#endif + extern int log_begin(const char *common_log_file, const char *error_log_file); extern void log_end(void); -extern int log_printf(enum log_level_t log_level, const char *app_file, int app_line, const char *format, ...); +extern int log_printf(enum log_level_t log_level, const char *app_file, int app_line, const char *format, ...) + LOG_PRINTF_FORMAT_ATTR; #define log_common(...) log_printf(LOG_LEVEL_COMMON, __FILE__, __LINE__, __VA_ARGS__) #define log_error(...) log_printf(LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__) diff --git a/src/Makefile.am b/src/Makefile.am index eea019f..8a161f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = bbsd test_PROGRAMS = test_trie_dict test_file_loader test_section_list test_lml test_ssh_server test_article_favor test_article_view_log \ - test_memory_pool test_bbs test_bwf test_hash_dict + test_memory_pool test_bbs test_bwf test_hash_dict test_ip_mask testdir = ${prefix}/test @@ -31,6 +31,7 @@ test_memory_pool_SOURCES = log.c memory_pool.c test_memory_pool.c test_bbs_SOURCES = bbs.c log.c test_bbs.c user_priv.c test_bwf_SOURCES = bwf.c log.c test_bwf.c test_hash_dict_SOURCES = hash_dict.c log.c memory_pool.c test_hash_dict.c +test_ip_mask_SOURCES = ip_mask.c test_ip_mask.c AM_CFLAGS = -I${srcdir}/../include -I${srcdir}/../utils/game ${LIBSSH_CFLAGS} ${MYSQLCLIENT_CFLAGS} ${SYSTEMD_CFLAGS} ${LIBPCRE2_CFLAGS} ${ICONV_CFLAGS} \ -std=c17 -Wall -Werror -Wformat -Wpedantic -Wformat-security -Wconversion \ diff --git a/src/article_cache.c b/src/article_cache.c index f02e05e..75cb794 100644 --- a/src/article_cache.c +++ b/src/article_cache.c @@ -129,7 +129,7 @@ int article_cache_generate(const char *cache_dir, const ARTICLE *p_article, cons if (header_len != cache.line_offsets[header_line_cnt]) { - log_debug("Header of article(aid=%d) is truncated from %ld to %ld\n, body_line=%ld, body_line_limit=%ld", + log_debug("Header of article(aid=%d) is truncated from %ld to %ld\n, body_line=%ld, body_line_limit=%d", p_article->aid, header_len, cache.line_offsets[header_line_cnt], header_line_cnt, MAX_SPLIT_FILE_LINES); header_len = (size_t)cache.line_offsets[header_line_cnt]; diff --git a/src/article_del.c b/src/article_del.c index 793d588..5fbb09d 100644 --- a/src/article_del.c +++ b/src/article_del.c @@ -34,6 +34,7 @@ int article_del(const SECTION_LIST *p_section, const ARTICLE *p_article) if (p_section == NULL || p_article == NULL) { log_error("NULL pointer error"); + return -1; } if (p_article->excerption) // Delete is not allowed diff --git a/src/article_post.c b/src/article_post.c index 4a0d631..c3d8b71 100644 --- a/src/article_post.c +++ b/src/article_post.c @@ -58,6 +58,7 @@ int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new) if (p_section == NULL || p_article_new == NULL) { log_error("NULL pointer error"); + return -1; } if (!checkpriv(&BBS_priv, p_section->sid, S_POST)) @@ -453,6 +454,7 @@ int article_modify(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTI if (p_section == NULL || p_article == NULL) { log_error("NULL pointer error"); + return -1; } if (p_article->excerption) // Modify is not allowed @@ -521,6 +523,13 @@ int article_modify(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTI reply_note = atoi(row[2]); } + else + { + log_error("Article content not found (aid=%d)", p_article->aid); + ret = -1; + goto cleanup; + } + mysql_free_result(rs); rs = NULL; @@ -754,6 +763,7 @@ int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTIC int sign_id = 0; int reply_note = 0; int full_quote = 0; + int cid = 0; long len; int ch; char *p, *q; @@ -770,6 +780,7 @@ int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTIC if (p_section == NULL || p_article == NULL) { log_error("NULL pointer error"); + return -1; } if (!checkpriv(&BBS_priv, p_section->sid, S_POST)) @@ -856,6 +867,8 @@ int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTIC if ((row = mysql_fetch_row(rs))) { + cid = atoi(row[0]); + content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { @@ -879,6 +892,13 @@ int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTIC // Remove control sequence len = str_filter(content_f, 0); } + else + { + log_error("Article content not found (aid=%d)", p_article->aid); + ret = -1; + goto cleanup; + } + mysql_free_result(rs); rs = NULL; @@ -1007,7 +1027,7 @@ int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTIC p_editor_data = editor_data_load(content); if (p_editor_data == NULL) { - log_error("editor_data_load(aid=%d, cid=%d) error", p_article->aid, atoi(row[0])); + log_error("editor_data_load(aid=%d, cid=%d) error", p_article->aid, cid); ret = -1; goto cleanup; } diff --git a/src/article_view_log.c b/src/article_view_log.c index 110c7b5..443e9c2 100644 --- a/src/article_view_log.c +++ b/src/article_view_log.c @@ -72,7 +72,7 @@ int article_view_log_load(int uid, ARTICLE_VIEW_LOG *p_view_log, int keep_inc) p_view_log->aid_base = malloc(sizeof(int32_t) * mysql_num_rows(rs)); if (p_view_log->aid_base == NULL) { - log_error("malloc(INT32 * %d) error: OOM", mysql_num_rows(rs)); + log_error("malloc(INT32 * %lu) error: OOM", (unsigned long)mysql_num_rows(rs)); mysql_free_result(rs); mysql_close(db); return -4; diff --git a/src/bbs_net.c b/src/bbs_net.c index 9fd87e5..d4e5d7c 100644 --- a/src/bbs_net.c +++ b/src/bbs_net.c @@ -199,7 +199,7 @@ static int load_bbsnet_conf(const char *file_config) p_menu_item = get_menu_item_by_id(&bbsnet_menu, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) error: NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) error: NULL pointer", menu_item_id); fclose(fin); unload_bbsnet_conf(); return -3; @@ -1383,7 +1383,7 @@ static int bbsnet_connect(int n) #ifdef HAVE_SYS_EPOLL_H if (epollfd != -1 && close(epollfd) < 0) { - log_error("close(epoll) error (%d)"); + log_error("close(epoll) error (%d)", errno); } #endif diff --git a/src/bwf.c b/src/bwf.c index 4df8de7..8113e25 100644 --- a/src/bwf.c +++ b/src/bwf.c @@ -57,7 +57,7 @@ int bwf_load(const char *filename) len_line = strnlen(line, sizeof(line) - 1); if (!feof(fp) && line[len_line - 1] != '\n') { - log_error("Data line %d (len=%d) is truncated", line_id, len_line); + log_error("Data line %d (len=%zu) is truncated", line_id, len_line); bwf_pattern_str[0] = '\0'; return -3; } @@ -80,7 +80,7 @@ int bwf_load(const char *filename) if (len_line + 2 > sizeof(bwf_pattern_str) - 1 - (size_t)(p - bwf_pattern_str)) { - log_error("Data in %s exceed length limit %d", filename, sizeof(bwf_pattern_str) - 1); + log_error("Data in %s exceed length limit %zu", filename, sizeof(bwf_pattern_str) - 1); bwf_pattern_str[0] = '\0'; return -3; } @@ -168,13 +168,13 @@ int check_badwords(char *str, char c_mask) i = ret - 1; if (ovector[i * 2] == -1 || ovector[i * 2 + 1] == -1) { - log_error("Bug: match pattern #%d of %d with invalid offsets [%d, %d)", + log_error("Bug: match pattern #%d of %d with invalid offsets [%zu, %zu)", i, match_count, ovector[i * 2], ovector[i * 2 + 1]); ret = -2; } else { - log_debug("Debug: match pattern #%d of %d at offsets [%d, %d]", + log_debug("Debug: match pattern #%d of %d at offsets [%zu, %zu]", i, match_count, ovector[i * 2], ovector[i * 2 + 1] - ovector[i * 2]); memset(str + ovector[i * 2], c_mask, ovector[i * 2 + 1] - ovector[i * 2]); total_match_count++; diff --git a/src/editor.c b/src/editor.c index 09a5633..b667bc5 100644 --- a/src/editor.c +++ b/src/editor.c @@ -111,7 +111,7 @@ EDITOR_DATA *editor_data_load(const char *p_data) p_data_line = memory_pool_alloc(p_mp_data_line); if (p_data_line == NULL) { - log_error("memory_pool_alloc() error: i = %d", i); + log_error("memory_pool_alloc() error: i = %ld", i); // Cleanup editor_data_cleanup(p_editor_data); return NULL; @@ -169,7 +169,7 @@ long editor_data_save(const EDITOR_DATA *p_editor_data, char *p_data, size_t buf { if (current_pos + p_editor_data->display_line_lengths[i] + 1 > buf_len) { - log_error("Data buffer not longer enough %d > %d", current_pos + p_editor_data->display_line_lengths[i] + 1, buf_len); + log_error("Data buffer not longer enough %ld > %zu", current_pos + p_editor_data->display_line_lengths[i] + 1, buf_len); p_data[current_pos] = '\0'; return -2; } @@ -367,7 +367,7 @@ int editor_data_insert(EDITOR_DATA *p_editor_data, long *p_display_line, long *p // Insert blank display line after last_display_line if (p_editor_data->display_line_total >= MAX_EDITOR_DATA_LINES) { - log_debug("display_line_total over limit %d >= %d", p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); + log_debug("display_line_total over limit %ld >= %d", p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); // Terminate prior display line with \n, to avoid error on cleanup if (display_line + i - 1 >= 0 && p_editor_data->display_line_lengths[display_line + i - 1] > 0) diff --git a/src/file_loader.c b/src/file_loader.c index 459c823..87ae7c5 100644 --- a/src/file_loader.c +++ b/src/file_loader.c @@ -100,7 +100,7 @@ int load_file(const char *filename) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } diff --git a/src/io.c b/src/io.c index 3e46c0d..9fc6b7a 100644 --- a/src/io.c +++ b/src/io.c @@ -1148,7 +1148,7 @@ int io_buf_conv(iconv_t cd, char *p_buf, int *p_buf_len, int *p_buf_offset, char if (out_bytes <= 0) { - log_error("No enough free space in p_conv, conv_len=%d, conv_size=%d", *p_conv_len, conv_size); + log_error("No enough free space in p_conv, conv_len=%d, conv_size=%zu", *p_conv_len, conv_size); return -2; } diff --git a/src/lml.c b/src/lml.c index 32347f3..16c9ecb 100644 --- a/src/lml.c +++ b/src/lml.c @@ -283,7 +283,7 @@ int lml_render(const char *str_in, char *str_out, int buf_len, int width, int qu #ifdef _DEBUG if (i >= str_in_len) { - log_error("Bug: i(%d) >= str_in_len(%d)", i, str_in_len); + log_error("Bug: i(%d) >= str_in_len(%zu)", i, str_in_len); break; } #endif diff --git a/src/main.c b/src/main.c index 271697f..9e80480 100644 --- a/src/main.c +++ b/src/main.c @@ -269,7 +269,7 @@ int main(int argc, char *argv[]) // Get EULA modification tm if (stat(DATA_EULA, &file_stat) == -1) { - log_error("stat(%s) error", DATA_EULA, errno); + log_error("stat(%s) error (%d)", DATA_EULA, errno); goto cleanup; } BBS_eula_tm = file_stat.st_mtim.tv_sec; diff --git a/src/menu.c b/src/menu.c index 1813d09..cffad15 100644 --- a/src/menu.c +++ b/src/menu.c @@ -123,7 +123,7 @@ int load_menu(MENU_SET *p_menu_set, const char *conf_file) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } @@ -776,7 +776,7 @@ int load_menu(MENU_SET *p_menu_set, const char *conf_file) // Clear line if (p_menu_set->p_menu_screen_buf_free + strlen(CTRL_SEQ_CLR_LINE) > q) { - log_error("Menu screen buffer depleted (%p + %d > %p)", p_menu_set->p_menu_screen_buf_free, q, strlen(CTRL_SEQ_CLR_LINE)); + log_error("Menu screen buffer depleted (%p + %zu > %p)", p_menu_set->p_menu_screen_buf_free, strlen(CTRL_SEQ_CLR_LINE), q); return -3; } p_menu_set->p_menu_screen_buf_free = stpcpy(p_menu_set->p_menu_screen_buf_free, CTRL_SEQ_CLR_LINE); @@ -882,7 +882,7 @@ int display_menu_cursor(MENU_SET *p_menu_set, int show) p_menu = get_menu_by_id(p_menu_set, menu_id); if (p_menu == NULL) { - log_error("get_menu_by_id(%d) return NULL pointer", menu_id); + log_error("get_menu_by_id(%lu) return NULL pointer", menu_id); return -1; } @@ -891,7 +891,7 @@ int display_menu_cursor(MENU_SET *p_menu_set, int show) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } @@ -917,7 +917,7 @@ static int display_menu_current_page(MENU_SET *p_menu_set) p_menu = get_menu_by_id(p_menu_set, menu_id); if (p_menu == NULL) { - log_error("get_menu_by_id(%d) return NULL pointer", menu_id); + log_error("get_menu_by_id(%lu) return NULL pointer", menu_id); return -1; } @@ -941,7 +941,7 @@ static int display_menu_current_page(MENU_SET *p_menu_set) p_menu_screen = get_menu_screen_by_id(p_menu_set, p_menu->screen_id); if (p_menu_screen == NULL) { - log_error("get_menu_screen_by_id(%d) return NULL pointer", p_menu->screen_id); + log_error("get_menu_screen_by_id(%lu) return NULL pointer", p_menu->screen_id); return -1; } @@ -1013,7 +1013,7 @@ int display_menu(MENU_SET *p_menu_set) p_menu = get_menu_by_id(p_menu_set, menu_id); if (p_menu == NULL) { - log_error("get_menu_by_id(%d) return NULL pointer", menu_id); + log_error("get_menu_by_id(%lu) return NULL pointer", menu_id); if (p_menu_set->choose_step > 0) { p_menu_set->choose_step--; @@ -1036,7 +1036,7 @@ int display_menu(MENU_SET *p_menu_set) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return EXITMENU; } @@ -1137,7 +1137,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu = get_menu_by_id(p_menu_set, menu_id); if (p_menu == NULL) { - log_error("get_menu_by_id(%d) return NULL pointer", menu_id); + log_error("get_menu_by_id(%lu) return NULL pointer", menu_id); if (p_menu_set->choose_step > 0) { p_menu_set->choose_step--; @@ -1164,7 +1164,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); p_menu_set->menu_item_pos[p_menu_set->choose_step] = 0; return REDRAW; } @@ -1215,7 +1215,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } @@ -1248,7 +1248,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id) @@ -1279,7 +1279,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id) @@ -1303,7 +1303,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } @@ -1330,7 +1330,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } @@ -1357,7 +1357,7 @@ int menu_control(MENU_SET *p_menu_set, int key) p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); + log_error("get_menu_item_by_id(%lu) return NULL pointer", menu_item_id); return -1; } diff --git a/src/menu_proc.c b/src/menu_proc.c index bd5659a..8b3b0db 100644 --- a/src/menu_proc.c +++ b/src/menu_proc.c @@ -363,7 +363,7 @@ int locate_article(void *param) if (sname == NULL || aid == NULL) { - log_error("top10_locate(%s) error: invalid parameter", param); + log_error("top10_locate(%s) error: invalid parameter", (const char *)param); return NOREDRAW; } diff --git a/src/net_server.c b/src/net_server.c index 3a153df..3520a4d 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -352,7 +352,7 @@ static int fork_server(void) #ifdef HAVE_SYS_EPOLL_H if (close(epollfd_server) < 0) { - log_error("close(epollfd_server) error (%d)"); + log_error("close(epollfd_server) error (%d)", errno); } #endif @@ -665,7 +665,7 @@ int net_server(const char *hostaddr, in_port_t port[]) log_error("epoll_ctl(socket_server[%d]) error (%d)", i, errno); if (close(epollfd_server) < 0) { - log_error("close(epoll) error (%d)"); + log_error("close(epoll) error (%d)", errno); } return -1; } @@ -744,7 +744,7 @@ int net_server(const char *hostaddr, in_port_t port[]) ret = hash_dict_inc(hash_dict_sockaddr_count, (in_addr_t)j, -1); if (ret <= 0) { - log_error("hash_dict_inc(hash_dict_sockaddr_count, %lu, -1) error: %d", (in_addr_t)j, ret); + log_error("hash_dict_inc(hash_dict_sockaddr_count, %u, -1) error: %d", (in_addr_t)j, ret); } ret = hash_dict_del(hash_dict_pid_sockaddr, (uint64_t)pid); @@ -835,7 +835,7 @@ int net_server(const char *hostaddr, in_port_t port[]) // Get EULA modification tm if (stat(DATA_EULA, &file_stat) == -1) { - log_error("stat(%s) error", DATA_EULA, errno); + log_error("stat(%s) error (%d)", DATA_EULA, errno); } else { @@ -994,7 +994,7 @@ int net_server(const char *hostaddr, in_port_t port[]) else { // Increase connection count from this IP - log_common("Accept %s connection from %s:%d, already have %d connections", + log_common("Accept %s connection from %s:%d, already have %ld connections", (SSH_v2 ? "SSH" : "telnet"), hostaddr_client, port_client, j); ret = hash_dict_inc(hash_dict_sockaddr_count, (uint64_t)sin.sin_addr.s_addr, 1); @@ -1007,7 +1007,7 @@ int net_server(const char *hostaddr, in_port_t port[]) } else { - log_error("Rejected %s connection from %s:%d over limit per IP (%d >= %d)", + log_error("Rejected %s connection from %s:%d over limit per IP (%ld >= %d)", (SSH_v2 ? "SSH" : "telnet"), hostaddr_client, port_client, j, BBS_max_client_per_ip); } } @@ -1029,7 +1029,7 @@ int net_server(const char *hostaddr, in_port_t port[]) #ifdef HAVE_SYS_EPOLL_H if (close(epollfd_server) < 0) { - log_error("close(epollfd_server) error (%d)"); + log_error("close(epollfd_server) error (%d)", errno); } #endif diff --git a/src/screen.c b/src/screen.c index 31df0f7..559109e 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1045,7 +1045,7 @@ int show_active_board(void) len = p_line_offsets[line_current + 1] - p_line_offsets[line_current]; if (len >= LINE_BUFFER_LEN) { - log_error("buffer overflow: len=%ld(%ld - %ld) line=%ld ", + log_error("buffer overflow: len=%ld(%ld - %ld) line=%d ", len, p_line_offsets[line_current + 1], p_line_offsets[line_current], line_current); len = LINE_BUFFER_LEN - 1; } diff --git a/src/section_list.c b/src/section_list.c index adcde46..6098c31 100644 --- a/src/section_list.c +++ b/src/section_list.c @@ -130,7 +130,7 @@ int article_block_init(const char *filename, int block_count) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } @@ -176,7 +176,7 @@ int article_block_init(const char *filename, int block_count) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } @@ -486,7 +486,7 @@ extern int section_list_init(const char *filename) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } @@ -535,7 +535,7 @@ extern int section_list_init(const char *filename) semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600); if (semid == -1) { - log_error("semget(section_list_pool_sem, size = %d) error (%d)", size, errno); + log_error("semget(section_list_pool_sem, size = %zu) error (%d)", size, errno); return -3; } @@ -556,14 +556,14 @@ extern int section_list_init(const char *filename) p_section_list_pool->p_trie_dict_section_by_name = trie_dict_create(); if (p_section_list_pool->p_trie_dict_section_by_name == NULL) { - log_error("trie_dict_create() OOM", BBS_max_section); + log_error("trie_dict_create() OOM, BBS_max_section=%d", BBS_max_section); return -2; } p_section_list_pool->p_trie_dict_section_by_sid = trie_dict_create(); if (p_section_list_pool->p_trie_dict_section_by_sid == NULL) { - log_error("trie_dict_create() OOM", BBS_max_section); + log_error("trie_dict_create() OOM, BBS_max_section=%d", BBS_max_section); return -2; } @@ -732,7 +732,7 @@ int section_list_update(SECTION_LIST *p_section, const char *sname, const char * if (trie_dict_set(p_section_list_pool->p_trie_dict_section_by_name, sname, index) < 0) { - log_error("trie_dict_set(section, %s, %d) error", sname, index); + log_error("trie_dict_set(section, %s, %ld) error", sname, index); return -2; } @@ -1132,8 +1132,6 @@ int section_list_update_article_ontop(SECTION_LIST *p_section, ARTICLE *p_articl p_section->p_ontop_articles[i] = p_article; p_section->ontop_article_count++; - - // TODO: debug } else // ontop == 0 { @@ -2066,7 +2064,7 @@ int section_list_rd_lock(SECTION_LIST *p_section) log_error("section_list_try_rd_lock() tried %d times on section %d", timer, sid); if (time(NULL) - tm_first_failure >= SECTION_DEAD_LOCK_TIMEOUT) { - log_error("Unable to acquire rd_lock for %d seconds", time(NULL) - tm_first_failure); + log_error("Unable to acquire rd_lock for %ld seconds", time(NULL) - tm_first_failure); #ifndef HAVE_SYSTEM_V section_list_reset_lock(p_section); log_error("Reset POSIX semaphore to resolve dead lock"); @@ -2114,7 +2112,7 @@ int section_list_rw_lock(SECTION_LIST *p_section) log_error("section_list_try_rw_lock() tried %d times on section %d", timer, sid); if (time(NULL) - tm_first_failure >= SECTION_DEAD_LOCK_TIMEOUT) { - log_error("Unable to acquire rw_lock for %d seconds", time(NULL) - tm_first_failure); + log_error("Unable to acquire rw_lock for %ld seconds", time(NULL) - tm_first_failure); #ifndef HAVE_SYSTEM_V section_list_reset_lock(p_section); log_error("Reset POSIX semaphore to resolve dead lock"); diff --git a/src/section_list_loader.c b/src/section_list_loader.c index 734dd22..67acf5a 100644 --- a/src/section_list_loader.c +++ b/src/section_list_loader.c @@ -595,7 +595,7 @@ int apply_article_op_log_from_db(int op_count_limit) // acquire lock of dest section if ((ret = section_list_rw_lock(p_section_dest)) < 0) { - log_error("section_list_rw_lock(sid = %d) error", p_section_dest); + log_error("section_list_rw_lock(sid = %d) error", p_section_dest->sid); break; } // Move topic @@ -607,7 +607,7 @@ int apply_article_op_log_from_db(int op_count_limit) // release lock of dest section if (section_list_rw_unlock(p_section_dest) < 0) { - log_error("section_list_rw_unlock(sid = %d) error", p_section_dest); + log_error("section_list_rw_unlock(sid = %d) error", p_section_dest->sid); ret = -1; } } diff --git a/src/str_process.c b/src/str_process.c index a488a70..1cbf877 100644 --- a/src/str_process.c +++ b/src/str_process.c @@ -68,6 +68,11 @@ int str_length(const char *str, int skip_ctrl_seq) c = (char)(c & 0xf0); while (c & 0x80) { + if (str[i + str_len] == '\0') + { + log_error("Truncated multi-byte sequence, i=%d, str_len=%d", i, str_len); + break; + } input_str[str_len] = str[i + str_len]; str_len++; c = (char)((c & 0x7f) << 1); @@ -132,6 +137,11 @@ int split_line(const char *buffer, int max_display_len, int *p_eol, int *p_displ c = (char)(c & 0xf0); while (c & 0x80) { + if (buffer[i + str_len] == '\0') + { + log_error("Truncated multi-byte sequence, i=%d, str_len=%d", i, str_len); + break; + } input_str[str_len] = buffer[i + str_len]; str_len++; c = (char)((c & 0x7f) << 1); @@ -199,7 +209,7 @@ long split_data_lines(const char *p_buf, int max_display_len, long *p_line_offse // Exceed max_line_cnt if (line_cnt + 1 >= line_offsets_count) { - log_debug("Line count %d reaches limit %d", line_cnt + 1, line_offsets_count); + log_debug("Line count %d reaches limit %ld", line_cnt + 1, line_offsets_count); return line_cnt; } diff --git a/src/test_ip_mask.c b/src/test_ip_mask.c new file mode 100644 index 0000000..60cb463 --- /dev/null +++ b/src/test_ip_mask.c @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * test_ip_mask + * - tester for IP address mask + * + * Copyright (C) 2004-2026 Leaflet + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ip_mask.h" +#include +#include + +// Longest expected output is "*.*.*.*" (7 bytes) + '\0' +#define TEST_STR_LEN 32 + +typedef struct _ip_mask_test_case_t +{ + const char *input; + int level; + char mask; + const char *expected; +} IP_MASK_TEST_CASE; + +static const IP_MASK_TEST_CASE test_cases[] = { + // level <= 0: string is left as is + {"192.168.1.100", 0, '*', "192.168.1.100"}, + {"192.168.1.100", -1, '*', "192.168.1.100"}, + {"192.168.1.100", -100, '*', "192.168.1.100"}, + // level 1: mask the last octet only + {"192.168.1.100", 1, '*', "192.168.1.*"}, + {"127.0.0.1", 1, '*', "127.0.0.*"}, + {"0.0.0.0", 1, '*', "0.0.0.*"}, + {"10.11.12.13", 1, '#', "10.11.12.#"}, + {"10.11.12.13", 1, '%', "10.11.12.%"}, + {"192.168.1.100:8080", 1, '*', "192.168.1.*"}, + // level 2: mask the last two octets + {"192.168.1.100", 2, '*', "192.168.*.*"}, + {"127.0.0.1", 2, '*', "127.0.*.*"}, + {"255.255.255.255", 2, '*', "255.255.*.*"}, + // level 3: mask the last three octets + {"192.168.1.100", 3, '*', "192.*.*.*"}, + {"127.0.0.1", 3, '*', "127.*.*.*"}, + // level 4: mask all octets + {"192.168.1.100", 4, '*', "*.*.*.*"}, + {"127.0.0.1", 4, '*', "*.*.*.*"}, + // level > 4: treated as level 4 + {"192.168.1.100", 5, '*', "*.*.*.*"}, + {"192.168.1.100", 100, '*', "*.*.*.*"}, + // Not a complete IPv4 address: nothing to mask when there are not enough '.' separators + {"192.168.1", 1, '*', "192.168.1"}, + {"192.168.1", 2, '*', "192.168.*.*"}, + {"localhost", 1, '*', "localhost"}, + {"localhost", 2, '*', "localhost"}, + // Blank string: no '.' separator to be found, the full string is masked only when level >= 4 + {"", 0, '*', ""}, + {"", 1, '*', ""}, + {"", 4, '*', "*.*.*.*"}, +}; + +static const int test_case_count = (int)(sizeof(test_cases) / sizeof(test_cases[0])); + +static const int octet_values[] = {0, 1, 9, 10, 99, 100, 127, 128, 168, 192, 254, 255}; +static const int octet_value_count = (int)(sizeof(octet_values) / sizeof(octet_values[0])); + +static int check_count = 0; +static int failed_count = 0; + +static void check_ip_mask(const char *input, int level, char mask, const char *expected, int verbose) +{ + char str[TEST_STR_LEN]; + const char *p; + + strncpy(str, input, sizeof(str) - 1); + str[sizeof(str) - 1] = '\0'; + + p = ip_mask(str, level, mask); + + check_count++; + + if (p != str) + { + failed_count++; + printf("FAILED: ip_mask(\"%s\", %d, '%c') returned a pointer other than the input\n", input, level, mask); + } + else if (strcmp(str, expected) != 0) + { + failed_count++; + printf("FAILED: ip_mask(\"%s\", %d, '%c') = \"%s\", expected \"%s\"\n", input, level, mask, str, expected); + } + else if (verbose) + { + printf("PASSED: ip_mask(\"%s\", %d, '%c') = \"%s\"\n", input, level, mask, str); + } +} + +static void check_ip_mask_all_levels(int a, int b, int c, int d) +{ + char input[TEST_STR_LEN]; + char expected[TEST_STR_LEN]; + + snprintf(input, sizeof(input), "%d.%d.%d.%d", a, b, c, d); + + for (int level = 0; level <= 4; level++) + { + switch (level) + { + case 0: + snprintf(expected, sizeof(expected), "%d.%d.%d.%d", a, b, c, d); + break; + case 1: + snprintf(expected, sizeof(expected), "%d.%d.%d.*", a, b, c); + break; + case 2: + snprintf(expected, sizeof(expected), "%d.%d.*.*", a, b); + break; + case 3: + snprintf(expected, sizeof(expected), "%d.*.*.*", a); + break; + default: + snprintf(expected, sizeof(expected), "*.*.*.*"); + break; + } + + check_ip_mask(input, level, '*', expected, 0); + } +} + +int main(int argc, char *argv[]) +{ + int i; + + printf("Testing #1 ...\n"); + + for (i = 0; i < test_case_count; i++) + { + check_ip_mask(test_cases[i].input, test_cases[i].level, test_cases[i].mask, test_cases[i].expected, 1); + } + + printf("Completed testing #1: %d of %d checks passed\n", check_count - failed_count, check_count); + + printf("Testing #2 ...\n"); + + for (i = 0; i < octet_value_count; i++) + { + check_ip_mask_all_levels(octet_values[i], + octet_values[(i * 3 + 1) % octet_value_count], + octet_values[(i * 5 + 2) % octet_value_count], + octet_values[(i * 7 + 3) % octet_value_count]); + } + + printf("Completed testing #2: %d of %d checks passed\n", check_count - failed_count, check_count); + + if (failed_count > 0) + { + printf("Failed: %d of %d checks\n", failed_count, check_count); + + return -1; + } + + printf("Done\n"); + + return 0; +} diff --git a/src/trie_dict.c b/src/trie_dict.c index 4196ee8..b974047 100644 --- a/src/trie_dict.c +++ b/src/trie_dict.c @@ -82,7 +82,7 @@ int trie_dict_init(const char *filename, int node_count_limit) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } diff --git a/src/user_list.c b/src/user_list.c index a551593..9af3281 100644 --- a/src/user_list.c +++ b/src/user_list.c @@ -210,7 +210,7 @@ int user_list_load(MYSQL *db, USER_LIST *p_list) intro_len = strlen((row[12] == NULL ? "" : row[12])); if (intro_len >= sizeof(p_list->user_intro_buf) - 1 - intro_buf_offset) { - log_error("OOM for user introduction: len=%d, i=%d", intro_len, i); + log_error("OOM for user introduction: len=%zu, i=%d", intro_len, i); break; } memcpy(p_list->user_intro_buf + intro_buf_offset, @@ -455,7 +455,7 @@ int user_list_pool_init(const char *filename) } if (ftruncate(fd, (off_t)size) == -1) { - log_error("ftruncate(size=%d) error (%d)", size, errno); + log_error("ftruncate(size=%zu) error (%d)", size, errno); close(fd); return -2; } @@ -500,7 +500,7 @@ int user_list_pool_init(const char *filename) semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600); if (semid == -1) { - log_error("semget(user_list_pool_sem, size = %d) error (%d)", size, errno); + log_error("semget(user_list_pool_sem, size = %zu) error (%d)", size, errno); return -3; } @@ -934,7 +934,7 @@ int user_list_rd_lock(void) if (time(NULL) - tm_first_failure >= USER_LIST_DEAD_LOCK_TIMEOUT) { - log_error("Unable to acquire rw_lock for %d seconds", time(NULL) - tm_first_failure); + log_error("Unable to acquire rw_lock for %ld seconds", time(NULL) - tm_first_failure); #ifndef HAVE_SYSTEM_V user_list_reset_lock(); log_error("Reset POSIX semaphore to resolve dead lock"); @@ -982,7 +982,7 @@ int user_list_rw_lock(void) if (time(NULL) - tm_first_failure >= USER_LIST_DEAD_LOCK_TIMEOUT) { - log_error("Unable to acquire rw_lock for %d seconds", time(NULL) - tm_first_failure); + log_error("Unable to acquire rw_lock for %ld seconds", time(NULL) - tm_first_failure); #ifndef HAVE_SYSTEM_V user_list_reset_lock(); log_error("Reset POSIX semaphore to resolve dead lock"); @@ -1377,7 +1377,7 @@ int query_user_info_by_username(const char *username_prefix, int max_user_cnt, } else // if (comp < 0) { - log_error("Bug: left=%d right=%d mid=%d"); + log_error("Bug: left=%d right=%d mid=%d", left, right, mid); ret = -2; goto cleanup; } @@ -1403,7 +1403,7 @@ int query_user_info_by_username(const char *username_prefix, int max_user_cnt, } else // if (comp > 0) { - log_error("Bug: left=%d right=%d mid=%d"); + log_error("Bug: left=%d right=%d mid=%d", left, right, mid); ret = -2; goto cleanup; } diff --git a/utils/lib/str_process.inc.php b/utils/lib/str_process.inc.php index 13d9d81..8c34d68 100644 --- a/utils/lib/str_process.inc.php +++ b/utils/lib/str_process.inc.php @@ -44,6 +44,10 @@ function str_length(string $str, bool $skip_ctrl_seq = false) : int while ($v2 & 0x80) { $i++; + if ($i >= $len) // Truncated multi-byte sequence + { + break; + } $c .= $str[$i]; $v2 = ($v2 & 0x7f) << 1; } @@ -106,6 +110,10 @@ function split_line(string $str, string $prefix = "", int $width = PHP_INT_MAX, while ($v2 & 0x80) { $i++; + if ($i >= $len) // Truncated multi-byte sequence + { + break; + } $c .= $str[$i]; $v2 = ($v2 & 0x7f) << 1; }