slweb

Једноставни генератор статичких веб страна
git clone https://git.sr.ht/~strahinja/slweb
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување f5c4a5db82f0d6bd47af671f62a738c92835be5e
родитељ ffebc77bebfa9c0a3447cd0ee35cb547e3dda432
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Fri, 23 Feb 2024 15:22:48 +0100

Update copyright dates; switch to OpenBSD strlcat,strlcpy,snprintf

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
MREADME | 2+-
MTODO | 2+-
Mdefs.h | 9++++++++-
Mslweb.1.in | 2+-
Mslweb.c | 462+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Astrlcat.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astrlcpy.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Mutf8.c | 2+-
Mutf8.h | 2+-
Mversion.h.in | 2+-
измењених датотека: 10, додавања: 478(+), брисања: 108(-)

diff --git a/README b/README @@ -44,7 +44,7 @@ License ------- slweb - Simple static website generator. -Copyright (C) 2020-2023 Страхиња Радић +Copyright (C) 2020-2024 Страхиња Радић This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/TODO b/TODO @@ -6,7 +6,7 @@ TODO [/] Real solution (children die with parent) - Is there actually any need? -[ ] Switch to strlcpy/strlcat +[x] Switch to strlcpy/strlcat [ ] Switch to POSIX make diff --git a/defs.h b/defs.h @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. Copyright (C) 2020-2023 Страхиња Радић. + * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ #ifndef __DEFS_H @@ -19,6 +19,13 @@ #include <sys/wait.h> #include <unistd.h> +#ifndef strlcpy +size_t strlcpy(char *dst, const char *src, size_t dsize); +#endif +#ifndef strlcat +size_t strlcat(char *dst, const char *src, size_t dsize); +#endif + #include "version.h" #include "utf8.h" diff --git a/slweb.1.in b/slweb.1.in @@ -36,7 +36,7 @@ slweb \- Simple static website generator .YS . .SH COPYRIGHT -slweb Copyright \(co 2020, 2021, 2022, 2023 Strahinya Radich. +slweb Copyright \(co 2020\-2024 Strahinya Radich. .br This program is licensed under GNU GPL v3 or later. See the file .I LICENSE diff --git a/slweb.c b/slweb.c @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. Copyright (C) 2020-2023 Страхиња Радић. + * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ #include "defs.h" @@ -272,7 +272,9 @@ set_basedir(char** basedir, size_t* basedir_size, const char* arg) *basedir_size = arg_len + 1; REALLOC(*basedir, char, *basedir_size); } - strcpy(*basedir, arg); + + if (strlcpy(*basedir, arg, *basedir_size) > *basedir_size) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); basedir_len = strlen(*basedir); if (*(*basedir + basedir_len - 1) == '/') *(*basedir + basedir_len - 1) = 0; @@ -294,7 +296,9 @@ set_global_link_prefix(char** global_link_prefix, *global_link_prefix_size = arg_len + 1; REALLOC(*global_link_prefix, char, *global_link_prefix_size); } - strcpy(*global_link_prefix, arg); + if (strlcpy(*global_link_prefix, arg, *global_link_prefix_size) + > *global_link_prefix_size) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); *(*global_link_prefix + arg_len) = 0; return 0; @@ -353,7 +357,10 @@ print_output(FILE* output, const char* fmt, ...) { csv_template_size = BUFSIZE; CALLOC(csv_template, u8, csv_template_size); - strcpy((char*)csv_template, buf); + if (strlcpy((char*)csv_template, buf, csv_template_size) + > csv_template_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } else { @@ -363,7 +370,10 @@ print_output(FILE* output, const char* fmt, ...) csv_template_size += BUFSIZE; REALLOC(csv_template, u8, csv_template_size); } - strcat((char*)csv_template, buf); + if (strlcat((char*)csv_template, buf, csv_template_size) + > csv_template_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } } else if (IN(state, ST_TSV_BODY)) @@ -375,7 +385,10 @@ print_output(FILE* output, const char* fmt, ...) { tsv_template_size = BUFSIZE; CALLOC(tsv_template, u8, tsv_template_size); - strcpy((char*)tsv_template, buf); + if (strlcpy((char*)tsv_template, buf, tsv_template_size) + > tsv_template_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } else { @@ -385,7 +398,10 @@ print_output(FILE* output, const char* fmt, ...) tsv_template_size += BUFSIZE; REALLOC(tsv_template, u8, tsv_template_size); } - strcat((char*)tsv_template, buf); + if (strlcat((char*)tsv_template, buf, tsv_template_size) + > tsv_template_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } } else @@ -585,9 +601,16 @@ process_git_log(FILE* output) pid_t result = 0; if (slash) - strcpy(basename, slash + 1); + { + if (strlcpy(basename, slash + 1, basename_size) > basename_size) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); + } else - strcpy(basename, input_filename); + { + if (strlcpy(basename, input_filename, basename_size) + > basename_size) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); + } u8* pipe_args[] = {(u8*)basename, NULL}; @@ -632,7 +655,10 @@ process_inline_stylesheet(FILE* output, const u8* css_filename, int output_yaml) css_pathname_size = basedir_size + css_filename_len + 1; CALLOC(css_pathname, char, css_pathname_size); - sprintf(css_pathname, "%s/%s", basedir, css_filename); + if (snprintf(css_pathname, css_pathname_size, "%s/%s", basedir, + css_filename) + > css_pathname_size) + warning(1, (u8*)"snprintf:%d: Overflow", __LINE__); if (!(css = fopen((const char*)css_pathname, "rt"))) exit(error(ENOENT, (u8*)"process_inline_stylesheet: No such file: %s", @@ -852,7 +878,8 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback) while (!feof(tsv) && (!tsv_iter || tsv_lineno <= tsv_iter)) { - u8* eol = NULL; + u8* eol = NULL; + size_t res = 0; if (!fgets((char*)bufline, BUFSIZE, tsv)) break; eol = (u8*)strchr((char*)bufline, '\n'); @@ -871,12 +898,25 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback) *ptoken = 0; if (tsv_lineno > 0 && current_register < MAX_TSV_REGISTERS) - strcpy((char*)tsv_register[current_register++], - (char*)token); + { + if ((res = strlcpy((char*)tsv_register + [current_register], + (char*)token, BUFSIZE)) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_register++; + } else if (tsv_lineno <= 0 && current_header < MAX_TSV_REGISTERS) - strcpy((char*)tsv_header[current_header++], - (char*)token); + { + if (strlcpy((char*)tsv_header[current_header], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_header++; + } RESET_TOKEN(token, ptoken, token_size); pbufline++; break; @@ -889,14 +929,26 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback) if (tsv_lineno > 0) { if (current_register < MAX_TSV_REGISTERS) - strcpy((char*)tsv_register[current_register++], - (char*)token); + { + if (strlcpy((char*)tsv_register[current_register], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_register++; + } } else { if (current_header < MAX_TSV_REGISTERS) - strcpy((char*)tsv_header[current_header++], - (char*)token); + { + if (strlcpy((char*)tsv_header[current_header], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_header++; + } } RESET_TOKEN(token, ptoken, token_size); @@ -1201,13 +1253,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback) *ptoken = 0; if (csv_lineno > 0 && current_register < MAX_CSV_REGISTERS) - strcpy((char*)csv_register - [current_register++], - (char*)token); + { + if (strlcpy((char*)csv_register + [current_register], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_register++; + } else if (csv_lineno <= 0 && current_header < MAX_CSV_REGISTERS) - strcpy((char*)csv_header[current_header++], - (char*)token); + { + if (strlcpy((char*)csv_header + [current_header], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_header++; + } RESET_TOKEN(token, ptoken, token_size); pbufline++; } @@ -1220,13 +1285,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback) *ptoken = 0; if (csv_lineno > 0 && current_register < MAX_CSV_REGISTERS) - strcpy((char*)csv_register - [current_register++], - (char*)token); + { + if (strlcpy((char*)csv_register + [current_register], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_register++; + } else if (csv_lineno <= 0 && current_header < MAX_CSV_REGISTERS) - strcpy((char*)csv_header[current_header++], - (char*)token); + { + if (strlcpy((char*)csv_header + [current_header], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_header++; + } RESET_TOKEN(token, ptoken, token_size); pbufline++; } @@ -1239,14 +1317,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback) if (csv_lineno > 0) { if (current_register < MAX_CSV_REGISTERS) - strcpy((char*)csv_register[current_register++], - (char*)token); + { + if (strlcpy((char*)csv_register[current_register], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_register++; + } } else { if (current_header < MAX_CSV_REGISTERS) - strcpy((char*)csv_header[current_header++], - (char*)token); + { + if (strlcpy((char*)csv_header[current_header], + (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + current_header++; + } } RESET_TOKEN(token, ptoken, token_size); @@ -1742,8 +1832,12 @@ process_incdir_subdir(FILE* output, const char* subdirname, if (footer_permalink_text && incdir_only_summary) { - if (ext_in_permalink) - strcat(link, timestamp_output_ext); + if (ext_in_permalink + && strlcat(link, timestamp_output_ext, + sizeof link) + > sizeof link) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); /* TODO: Get rid of orphan <p> just before * <footer>; would probably need another flag @@ -1929,11 +2023,29 @@ format_date(const u8* date_arg, const char* timestamp_format) while (*ptimestamp_format) { if (*ptimestamp_format == 'd' || *ptimestamp_format == 'D') - strcat((char*)formatted_date, (char*)day); + { + if (strlcat((char*)formatted_date, (char*)day, + DATEBUFSIZE) + > DATEBUFSIZE) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); + } else if (*ptimestamp_format == 'm' || *ptimestamp_format == 'M') - strcat((char*)formatted_date, (char*)month); + { + if (strlcat((char*)formatted_date, (char*)month, + DATEBUFSIZE) + > DATEBUFSIZE) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); + } else if (*ptimestamp_format == 'y' || *ptimestamp_format == 'Y') - strcat((char*)formatted_date, (char*)year); + { + if (strlcat((char*)formatted_date, (char*)year, + DATEBUFSIZE) + > DATEBUFSIZE) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); + } else *(formatted_date + strlen((char*)formatted_date)) = *ptimestamp_format; @@ -2011,7 +2123,9 @@ process_macro_def(FILE* output, const u8* token, pmacros = macros + macros_count - 1; } CALLOC(pmacros->key, u8, KEYSIZE); - strcpy((char*)pmacros->key, (char*)token + 2); + if (strlcpy((char*)pmacros->key, (char*)token + 2, KEYSIZE) + > KEYSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); pmacros->value = NULL; pmacros->value_size = 0; } @@ -2488,8 +2602,10 @@ process_inline_footnote(const u8* token, const int read_yaml_macros_and_links, CALLOC(inline_footnotes[inline_footnote_count - 1], u8, token_len + 1); - strcpy((char*)inline_footnotes[inline_footnote_count - 1], - (char*)token); + if (strlcpy((char*)inline_footnotes[inline_footnote_count - 1], + (char*)token, token_len + 1) + > token_len + 1) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); *(inline_footnotes[inline_footnote_count - 1] + token_len) = 0; } else @@ -2529,7 +2645,9 @@ process_footnote(FILE* output, const u8* token, const int footnote_definition, pfootnotes = footnotes + footnote_count - 1; } CALLOC(pfootnotes->key, u8, KEYSIZE); - strcpy((char*)pfootnotes->key, (char*)token); + if (strlcpy((char*)pfootnotes->key, (char*)token, KEYSIZE) + > KEYSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); pfootnotes->value = NULL; pfootnotes->value_size = 0; } @@ -2718,8 +2836,10 @@ begin_article(FILE* output, const char* source_filename, const u8* link_prefix, u8* permalink_macro = get_value(macros, macros_count, (u8*)"permalink", NULL); - if (ext_in_permalink) - strcat(link, timestamp_output_ext); + if (ext_in_permalink + && strlcat(link, timestamp_output_ext, sizeof link) + > sizeof link) + warning(1, (u8*)"strlcat:%d: Overflow", __LINE__); if (permalink_url) process_timestamp(output, link_prefix, permalink_url, @@ -2868,10 +2988,18 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count, *pvars = *vars + *vars_count - 1; } CALLOC((*pvars)->key, u8, KEYSIZE); - strcpy((char*)(*pvars)->key, (char*)var_key); + if (strlcpy((char*)(*pvars)->key, (char*)var_key, + KEYSIZE) + > KEYSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); (*pvars)->value_size = strlen((char*)token) + 1; CALLOC((*pvars)->value, u8, (*pvars)->value_size); - strcpy((char*)(*pvars)->value, (char*)token); + if (strlcpy((char*)(*pvars)->value, (char*)token, + (*pvars)->value_size) + > (*pvars)->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } } free(var_key); @@ -3120,7 +3248,10 @@ do_line: pvars = vars + vars_count - 1; } CALLOC(pvars->key, u8, KEYSIZE); - strcpy((char*)pvars->key, (char*)token); + if (strlcpy((char*)pvars->key, (char*)token, KEYSIZE) + > KEYSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); pvars->value = NULL; pvars->value_size = 0; @@ -3172,7 +3303,11 @@ do_line: if (token_len + entity_len < BUFSIZE) { - strcat((char*)token, (char*)entity); + if (strlcat((char*)token, (char*)entity, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += entity_len; } } @@ -3213,7 +3348,11 @@ do_line: if (token_len + entity_len < BUFSIZE) { - strcat((char*)token, (char*)entity); + if (strlcat((char*)token, (char*)entity, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += entity_len; } } @@ -3255,7 +3394,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3337,7 +3480,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3444,7 +3591,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3487,7 +3638,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3641,7 +3796,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3685,7 +3844,11 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -3760,7 +3923,11 @@ do_line: { size_t br_len = strlen("<br>"); *ptoken = 0; - strcat((char*)ptoken, "<br>"); + if (strlcat((char*)ptoken, "<br>", + token_size - (ptoken - token)) + > token_size - (ptoken - token)) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += br_len; output_firstcol = 0; pline++; @@ -3769,7 +3936,10 @@ do_line: else if (IN(state, ST_LINK_MACRO)) { *ptoken = 0; - strcpy((char*)link_macro, (char*)token); + if (strlcpy((char*)link_macro, (char*)token, BUFSIZE) + > BUFSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); *(link_macro + strlen((char*)token)) = 0; RESET_TOKEN(token, ptoken, token_size); state &= ~ST_LINK_MACRO; @@ -3817,16 +3987,24 @@ do_line: REALLOC(pmacros->value, u8, pmacros->value_size); } - strcat((char*)pmacros->value, - (char*)token); + if (strlcat((char*)pmacros->value, + (char*)token, + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } else { pmacros->value_size = token_len + 1; CALLOC(pmacros->value, u8, pmacros->value_size); - strcpy((char*)pmacros->value, - (char*)token); + if (strlcpy((char*)pmacros->value, + (char*)token, + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } } } @@ -3923,12 +4101,12 @@ do_line: REALLOC(pmacros->value, u8, pmacros->value_size); } - strcat((char*)pmacros->value, "{"); - if (end_tag) - strcat((char*)pmacros->value, "/"); - strcat(strcat((char*)pmacros->value, - (char*)token), - "}"); + if (snprintf((char*)pmacros->value, + pmacros->value_size, "{%s%s}", + end_tag ? "/" : "", (char*)token) + > pmacros->value_size) + warning(1, (u8*)"snprintf:%d: Overflow", + __LINE__); } *token = 0; @@ -4011,9 +4189,13 @@ do_line: *ptoken = 0; token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) + if (token_len + tag_len + 1 < token_size) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } } @@ -4213,7 +4395,10 @@ do_line: { size_t lt_len = strlen("&lt;"); *ptoken = 0; - strcat((char*)token, "&lt;"); + if (strlcat((char*)token, "&lt;", token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += lt_len; pline++; colno++; @@ -4402,7 +4587,10 @@ do_line: if (token_len + tag_len < BUFSIZE) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } @@ -4429,9 +4617,12 @@ do_line: *ptoken = 0; token_len = strlen((char*)token); - if (token_len + tag_len < BUFSIZE) + if (token_len + tag_len + 1 < token_size) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } @@ -4465,9 +4656,12 @@ do_line: *ptoken = 0; token_len = strlen((char*)token); - if (token_len + tag_len + 1 < BUFSIZE) + if (token_len + tag_len + 1 < token_size) { - strcat((char*)token, (char*)tag); + if (strlcat((char*)token, (char*)tag, token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += tag_len; } state &= ~ST_LINK_SPAN; @@ -4618,7 +4812,11 @@ do_line: plinks = links + links_count - 1; } CALLOC(plinks->key, u8, KEYSIZE); - strcpy((char*)plinks->key, (char*)token); + if (strlcpy((char*)plinks->key, (char*)token, + KEYSIZE) + > KEYSIZE) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); plinks->value = NULL; plinks->value_size = 0; pline += 2; @@ -4647,7 +4845,11 @@ do_line: link_size = token_len + 1; CALLOC(link_text, u8, link_size); } - strcpy((char*)link_text, (char*)token); + if (strlcpy((char*)link_text, (char*)token, + link_size) + > link_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); *(link_text + token_len) = 0; pline += 2; colno += 2; @@ -4883,7 +5085,10 @@ do_line: { size_t quot_len = strlen("&quot;"); *ptoken = 0; - strcat((char*)token, "&quot;"); + if (strlcat((char*)token, "&quot;", token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += quot_len; pline++; } @@ -4899,7 +5104,10 @@ do_line: { size_t quot_len = strlen("&amp;"); *ptoken = 0; - strcat((char*)token, "&amp;"); + if (strlcat((char*)token, "&amp;", token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); ptoken += quot_len; pline++; } @@ -4929,7 +5137,9 @@ done_line: } pvars->value_size = strlen((char*)token) + 1; CALLOC(pvars->value, u8, pvars->value_size); - strcpy((char*)pvars->value, (char*)token); + if (strlcpy((char*)pvars->value, (char*)token, pvars->value_size) + > pvars->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__); } else if (keep_token) { @@ -4940,8 +5150,11 @@ done_line: REALLOC(token, u8, token_size); ptoken = token + old_size - 1; } - strcat((char*)token, - ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n"); + if (strlcat((char*)token, + ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n", + token_size) + > token_size) + warning(1, (u8*)"strlcat:%d: Overflow", __LINE__); ptoken++; *ptoken = 0; } @@ -4974,18 +5187,34 @@ done_line: REALLOC(pmacros->value, u8, pmacros->value_size); } - strcat((char*)pmacros->value, - (char*)token); - strcat((char*)pmacros->value, "\n"); + if (strlcat((char*)pmacros->value, + (char*)token, + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); + if (strlcat((char*)pmacros->value, "\n", + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } else { pmacros->value_size = BUFSIZE; CALLOC(pmacros->value, u8, pmacros->value_size); - strcpy((char*)pmacros->value, - (char*)token); - strcat((char*)pmacros->value, "\n"); + if (strlcpy((char*)pmacros->value, + (char*)token, + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + if (strlcat((char*)pmacros->value, "\n", + pmacros->value_size) + > pmacros->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } skip_macro_read:; } @@ -5014,18 +5243,34 @@ done_line: REALLOC(pfootnotes->value, u8, pfootnotes->value_size); } - strcat((char*)pfootnotes->value, - (char*)token); - strcat((char*)pfootnotes->value, "\n"); + if (strlcat((char*)pfootnotes->value, + (char*)token, + pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); + if (strlcat((char*)pfootnotes->value, + "\n", pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } else { pfootnotes->value_size = BUFSIZE; CALLOC(pfootnotes->value, u8, pfootnotes->value_size); - strcpy((char*)pfootnotes->value, - (char*)token); - strcat((char*)pfootnotes->value, "\n"); + if (strlcpy((char*)pfootnotes->value, + (char*)token, + pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); + if (strlcat((char*)pfootnotes->value, + "\n", pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } *token = 0; ptoken = token; @@ -5048,8 +5293,12 @@ done_line: = strlen((char*)token) + 1; CALLOC(plinks->value, u8, plinks->value_size); - strcpy((char*)plinks->value, - (char*)token); + if (strlcpy((char*)plinks->value, + (char*)token, + plinks->value_size) + > plinks->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } } else if (IN(state, ST_HEADING)) @@ -5139,16 +5388,24 @@ done_line: REALLOC(pfootnotes->value, u8, pfootnotes->value_size); } - strcat((char*)pfootnotes->value, - (char*)token); + if (strlcat((char*)pfootnotes->value, + (char*)token, + pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); } else { pfootnotes->value_size = token_len + 1; CALLOC(pfootnotes->value, u8, pfootnotes->value_size); - strcpy((char*)pfootnotes->value, - (char*)token); + if (strlcpy((char*)pfootnotes->value, + (char*)token, + pfootnotes->value_size) + > pfootnotes->value_size) + warning(1, (u8*)"strlcpy:%d: Overflow", + __LINE__); } *token = 0; ptoken = token; @@ -5391,7 +5648,10 @@ main(const int argc, const char** argv) buffer_size += BUFSIZE; REALLOC(buffer, u8, buffer_size); } - strcat((char*)buffer, (char*)bufline); + if (strlcat((char*)buffer, (char*)bufline, buffer_size) + > buffer_size) + warning(1, (u8*)"strlcat:%d: Overflow", + __LINE__); buffer_len += bufline_len; } free(bufline); diff --git a/strlcat.c b/strlcat.c @@ -0,0 +1,54 @@ +/* $OpenBSD: strlcat.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */ + +/* + * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> + +/* + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t dsize) +{ + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; + + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; + + return(dlen + (src - osrc)); /* count does not include NUL */ +} diff --git a/strlcpy.c b/strlcpy.c @@ -0,0 +1,49 @@ +/* $OpenBSD: strlcpy.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */ + +/* + * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> + +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ +} diff --git a/utf8.c b/utf8.c @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. Copyright (C) 2020-2023 Страхиња Радић. + * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ #include "utf8.h" diff --git a/utf8.h b/utf8.h @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. Copyright (C) 2020-2023 Страхиња Радић. + * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ #include <stdint.h> diff --git a/version.h.in b/version.h.in @@ -1,5 +1,5 @@ /* This program is licensed under the terms of GNU GPL v3 or (at your option) - * any later version. Copyright (C) 2020-2023 Страхиња Радић. + * any later version. Copyright (C) 2020-2024 Страхиња Радић. * See the file LICENSE for exact copyright and license details. */ #define PROGRAMNAME "slweb"