чување e17256bbcc3d4c07ec7764e587dea094df966afa
родитељ 9c6c2f06f2437b67a77d25646adb7bb50b3e109c
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Wed, 6 Mar 2024 21:54:46 +0100
Switch to strlcpy, strlcat
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 3 | --- |
| M | TODO.done | | | 3 | +++ |
| M | config.mk | | | 4 | ++-- |
| M | draw.c | | | 20 | ++++++++++++++++---- |
| M | po.c | | | 168 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
| M | poe.c | | | 176 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
| A | strlcat.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | strlcpy.c | | | 49 | +++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | util.c | | | 77 | +++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
| M | util.h | | | 16 | +++++++++++++--- |
измењених датотека: 10, додавања: 448(+), брисања: 122(-)
diff --git a/TODO b/TODO
@@ -1,9 +1,6 @@
TODO
====
-[ ] Switch to strlcpy, strlcat similar to sled; compare util.c and util.h to
- versions of those files from sled
-
[ ] Add pledge(2) and unveil(2)
[ ] Support Yudit's nonstandard PO format (no empty lines between individual
diff --git a/TODO.done b/TODO.done
@@ -1,6 +1,9 @@
Done todos
==========
+[x] Switch to strlcpy, strlcat similar to sled; compare util.c and util.h to
+ versions of those files from sled
+
[/] Replace strn* -> strc*: like str[^n]*, but with configurable string
ending character (for msgstr, which has multiple lines delimited
with '\n')
diff --git a/config.mk b/config.mk
@@ -6,9 +6,9 @@ CFLAGS = -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L \
# -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
INSTALL = install
LIBS =
-SRC = draw.c po.c poe.c util.c #strlcat.c strlcpy.c
+SRC = draw.c po.c poe.c strlcat.c strlcpy.c util.c
HEADERS = config.h draw.h po.h termbox.h util.h version.h
-OBJS = draw.o po.o poe.o util.o #strlcat.o strlcpy.o
+OBJS = draw.o po.o poe.o strlcat.o strlcpy.o util.o
PREFIX = /usr/local
PROG = poe
diff --git a/draw.c b/draw.c
@@ -60,6 +60,8 @@ const char* prompt_cancel_dirty = "Entry changed, save [y/n/ESC]?";
const char* prompt_overwrite = "Not empty, overwrite? [y/n/ESC]?";
/* clang-format on */
+int print_error(const int code, const char* msg, ...);
+
void
init_bufferline(struct BufferLine* bl)
{
@@ -612,9 +614,18 @@ draw_editbox(const struct DrawState* state)
struct PoEntry* entry = state->entries + state->msgid_number - 1;
size_t dlen = 0;
- strcpy(flags_buf, "[ ");
+ if (strlcpy(flags_buf, "[ ", MAXFLAGSBUF + 4) >= MAXFLAGSBUF + 4)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
format_flags(flags_buf + 2, MAXFLAGSBUF, entry);
- strcpy(flags_buf + 2 + MAXFLAGSBUF - 1, " ]");
+ if (strlcpy(flags_buf + 2 + MAXFLAGSBUF - 1, " ]", MAXFLAGSBUF + 4 - 2)
+ >= MAXFLAGSBUF + 4 - 2)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
startx = w > maxx ? 0 : (maxx - w) / 2;
endx = w > maxx ? maxx - 1 : startx + w;
@@ -689,13 +700,14 @@ draw_editbox(const struct DrawState* state)
char sbuf[MAXBUFLINE];
if (entry->msgstr_count > 1)
- sprintf(sbuf, "%d[%d]:%d[%d]/%d (plural: %d/%d)",
+ snprintf(sbuf, MAXBUFLINE, "%d[%d]:%d[%d]/%d (plural: %d/%d)",
state->input_display_column,
state->input_first_shown_column, state->input_row,
state->input_first_shown_row, state->input_rows_count,
state->msgstr_index + 1, entry->msgstr_count);
else
- sprintf(sbuf, "%d[%d]:%d[%d]/%d", state->input_display_column,
+ snprintf(sbuf, MAXBUFLINE, "%d[%d]:%d[%d]/%d",
+ state->input_display_column,
state->input_first_shown_column, state->input_row,
state->input_first_shown_row, state->input_rows_count);
draw_string(startx + 1, endy - 2, DLG_FG, DLG_BG, sbuf,
diff --git a/po.c b/po.c
@@ -20,6 +20,8 @@
extern const char* errors[];
extern const char* flag_strings[];
+int print_error(const int code, const char* msg, ...);
+
char*
format_flags(char* buffer, const size_t max, const struct PoEntry* entry)
{
@@ -415,8 +417,8 @@ load_file(struct DrawState* dstate, long* lineno, long* col)
FILE* input = NULL;
char input_line[MAXBUFLINE];
/* lines to tolerate the lack of msgid */
- int msgid_counter = PO_DETECTION_LINES;
- int msgstr_index = -1;
+ int msgid_counter = PO_DETECTION_LINES;
+ int msgstr_index = -1;
size_t non_obsolete_sofar = 0;
dstate->msgid_size = 0;
@@ -460,8 +462,9 @@ load_file(struct DrawState* dstate, long* lineno, long* col)
return LOAD_ERR_NOT_PO_FILE;
}
else if (result == PARSE_ERR_SYNTAX)
- sprintf(dstate->error, "%s:%ld:%ld: Syntax error",
- dstate->filename, *lineno, *col);
+ snprintf(dstate->error, MAXBUFLINE,
+ "%s:%ld:%ld: Syntax error", dstate->filename,
+ *lineno, *col);
else
{
free(dstate->entries);
@@ -483,7 +486,13 @@ load_file(struct DrawState* dstate, long* lineno, long* col)
entry->obsolete = 1;
#ifndef PLURAL_STRING
if (has_plural_msgid && !dstate->entries->plural_forms)
- strcpy(dstate->error, errors[ERR_NO_PLURAL_FORMS]);
+ if (strlcpy(dstate->error, errors[ERR_NO_PLURAL_FORMS],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
#endif
}
@@ -497,7 +506,7 @@ load_file(struct DrawState* dstate, long* lineno, long* col)
current = dstate->entries;
dstate->obsolete_at_end_count = 0;
- non_obsolete_sofar = 0;
+ non_obsolete_sofar = 0;
while (current != dstate->entries + dstate->real_msgid_count)
{
if (!current->obsolete)
@@ -546,8 +555,16 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count,
if (stat(real_filename, &st) == -1)
return SAVE_ERR_CANT_STAT_FILE;
}
- strcpy(backup_filename, filename);
- strcat(backup_filename, backup_suffix);
+ if (strlcpy(backup_filename, filename, MAXPATH) >= MAXPATH)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+ if (strlcat(backup_filename, backup_suffix, MAXPATH) >= MAXPATH)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
if (rename(rfn_len > 0 ? real_filename : filename,
backup_filename)
== -1)
@@ -583,16 +600,19 @@ save_comments:
char* u8_comment = NULL;
for (size_t c = 0; c < current->comment_lines; c++)
{
- size_t len = u32_strlen(*(current->comments + c)) + 1;
+ size_t len = u32_strlen(*(current->comments + c));
+ size_t size = len * UTF8REPMAX + 1;
if (!u8_comment)
- u8_comment = calloc(len * UTF8REPMAX, 1);
+ {
+ u8_comment = malloc(size);
+ memset(u8_comment, 0, size);
+ }
else
- u8_comment
- = realloc(u8_comment, len * UTF8REPMAX);
+ u8_comment = realloc(u8_comment, size);
if (!u8_comment)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_comment,
- *(current->comments + c), len * UTF8REPMAX);
+ unicode_string_to_u8(u8_comment, size,
+ *(current->comments + c), len);
fprintf(output, "#%s%s\n", current->obsolete ? "~" : "",
u8_comment);
}
@@ -603,18 +623,22 @@ save_comments:
char* u8_trans_comment = NULL;
for (size_t tc = 0; tc < current->trans_comment_lines; tc++)
{
- size_t len = u32_strlen(*(current->trans_comments + tc))
- + 1;
+ size_t len
+ = u32_strlen(*(current->trans_comments + tc));
+ size_t size = len * UTF8REPMAX + 1;
+
if (!u8_trans_comment)
- u8_trans_comment = calloc(len * UTF8REPMAX, 1);
+ {
+ u8_trans_comment = malloc(size);
+ memset(u8_trans_comment, 0, size);
+ }
else
- u8_trans_comment = realloc(u8_trans_comment,
- len * UTF8REPMAX);
+ u8_trans_comment
+ = realloc(u8_trans_comment, size);
if (!u8_trans_comment)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_trans_comment,
- *(current->trans_comments + tc),
- len * UTF8REPMAX);
+ unicode_string_to_u8(u8_trans_comment, size,
+ *(current->trans_comments + tc), len);
fprintf(output, "#.%s%s\n",
u8_trans_comment[0] == 0 ? "" : " ",
u8_trans_comment);
@@ -673,9 +697,8 @@ save_obsolete_check:
if (current->msgid)
{
- size_t msgid_size = current->msgid_size * UTF8REPMAX;
- size_t num_lines = u32_lines_in_string(current->msgid, 1,
- SAVE_WRAP_WIDTH);
+ size_t num_lines = u32_lines_in_string(current->msgid, 1,
+ SAVE_WRAP_WIDTH);
if ((num_lines > 1)
&& (u32_strlen(current->msgid)
@@ -687,7 +710,8 @@ save_obsolete_check:
while (*pumsgid)
{
- size_t len = 0;
+ size_t len = 0;
+ size_t size;
char* u8_msgid = NULL;
const uint32_t* old_pumsgid = pumsgid;
@@ -696,23 +720,34 @@ save_obsolete_check:
if (len == 0)
continue;
- u8_msgid = calloc(len + 1, UTF8REPMAX);
+ size = len * UTF8REPMAX + 1;
+
+ u8_msgid = malloc(size);
if (!u8_msgid)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgid, old_pumsgid, len);
+ memset(u8_msgid, 0, size);
+
+ unicode_string_to_u8(u8_msgid, size,
+ old_pumsgid, len);
fprintf(output, "\"%s\"\n", u8_msgid);
free(u8_msgid);
}
}
else
{
- char* u8_msgid
- = calloc(current->msgid_size, UTF8REPMAX);
+ size_t size;
+ char* u8_msgid = NULL;
+
+ size = current->msgid_size * UTF8REPMAX + 1;
+ u8_msgid = malloc(size);
if (!u8_msgid)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgid, current->msgid,
- msgid_size);
+
+ memset(u8_msgid, 0, size);
+
+ unicode_string_to_u8(u8_msgid, size, current->msgid,
+ current->msgid_size);
fprintf(output, "msgid \"%s\"\n", u8_msgid);
free(u8_msgid);
}
@@ -722,8 +757,6 @@ save_obsolete_check:
if (current->msgid_plural)
{
- size_t msgid_plural_size
- = current->msgid_plural_size * UTF8REPMAX;
size_t num_lines = u32_lines_in_string(current->msgid_plural, 1,
SAVE_WRAP_WIDTH);
@@ -740,29 +773,42 @@ save_obsolete_check:
size_t len = 0;
char* u8_msgid = NULL;
const uint32_t* old_pumsgid = pumsgid;
+ size_t size;
len = u32_next_line(current->msgid_plural,
&pumsgid, 1, SAVE_WRAP_WIDTH);
if (len == 0)
continue;
- u8_msgid = calloc(len + 1, UTF8REPMAX);
+ size = len * UTF8REPMAX + 1;
+ u8_msgid = malloc(size);
if (!u8_msgid)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgid, old_pumsgid, len);
+ memset(u8_msgid, 0, size);
+
+ unicode_string_to_u8(u8_msgid, size,
+ old_pumsgid, len);
fprintf(output, "\"%s\"\n", u8_msgid);
free(u8_msgid);
}
}
else
{
- char* u8_msgid = calloc(current->msgid_plural_size,
- UTF8REPMAX);
+ char* u8_msgid = NULL;
+ size_t size;
+ size_t msgid_plural_len;
+
+ size = current->msgid_plural_size * UTF8REPMAX + 1;
+ u8_msgid = malloc(size);
if (!u8_msgid)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgid, current->msgid_plural,
- msgid_plural_size);
+
+ memset(u8_msgid, 9, size);
+
+ msgid_plural_len = u32_strlen(current->msgid_plural);
+ unicode_string_to_u8(u8_msgid, size,
+ current->msgid_plural, msgid_plural_len);
fprintf(output, "msgid_plural \"%s\"\n", u8_msgid);
free(u8_msgid);
}
@@ -793,7 +839,8 @@ save_obsolete_check:
while (*pumsgstr)
{
- size_t len = 0;
+ size_t len = 0;
+ size_t size;
char* u8_msgstr = NULL;
const uint32_t* old_pumsgstr = pumsgstr;
@@ -807,12 +854,15 @@ save_obsolete_check:
if (len == 0)
continue;
- u8_msgstr = calloc(len + 1, UTF8REPMAX);
+ size = len * UTF8REPMAX + 1;
+ u8_msgstr = malloc(size);
if (!u8_msgstr)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgstr, old_pumsgstr,
- len);
+ memset(u8_msgstr, 0, size);
+
+ unicode_string_to_u8(u8_msgstr, size,
+ old_pumsgstr, len);
if (first_entry
&& starts_with(u8_msgstr,
"PO-Revision-Date: "))
@@ -858,9 +908,13 @@ save_obsolete_check:
fprintf(output, "msgstr[%d] \"\"\n", i);
else
{
- char u8_msgstr[MAXMSGLINE * UTF8REPMAX];
- unicode_string_to_u8(u8_msgstr, *current->msgstr,
- MAXMSGLINE * UTF8REPMAX);
+ size_t size = MAXMSGLINE * UTF8REPMAX + 1;
+ char u8_msgstr[size];
+ size_t msgstr_len;
+
+ msgstr_len = u32_strlen(*current->msgstr);
+ unicode_string_to_u8(u8_msgstr, size, *current->msgstr,
+ msgstr_len);
fprintf(output, "msgstr \"%s\"\n", u8_msgstr);
}
}
@@ -882,7 +936,8 @@ save_obsolete_check:
while (*pumsgstr)
{
- size_t len = 0;
+ size_t len = 0;
+ size_t size;
char* u8_msgstr = NULL;
const uint32_t* old_pumsgstr = pumsgstr;
@@ -892,11 +947,14 @@ save_obsolete_check:
if (len == 0)
continue;
- u8_msgstr = calloc(len + 1, UTF8REPMAX);
+ size = len * UTF8REPMAX + 1;
+ u8_msgstr = malloc(size);
if (!u8_msgstr)
return SAVE_ERR_CANT_ALLOC;
- unicode_string_to_u8(u8_msgstr,
+ memset(u8_msgstr, 0, size);
+
+ unicode_string_to_u8(u8_msgstr, size,
old_pumsgstr, len);
fprintf(output, "\"%s\"\n", u8_msgstr);
free(u8_msgstr);
@@ -904,10 +962,12 @@ save_obsolete_check:
}
else
{
- char u8_msgstr[MAXMSGLINE * UTF8REPMAX];
- unicode_string_to_u8(u8_msgstr,
- *(current->msgstr + m),
- MAXMSGLINE * UTF8REPMAX);
+ size_t size = MAXMSGLINE * UTF8REPMAX + 1;
+ char u8_msgstr[size];
+ size_t msgstr_len;
+ msgstr_len = u32_strlen(*(current->msgstr + m));
+ unicode_string_to_u8(u8_msgstr, size,
+ *(current->msgstr + m), msgstr_len);
fprintf(output, "msgstr[%ld] \"%s\"\n", m,
u8_msgstr);
}
diff --git a/poe.c b/poe.c
@@ -120,7 +120,12 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
if (state->show_help)
{
- strcpy(state->error, errors[ERR_DLG_OPEN_QUIT]);
+ if (strlcpy(state->error, errors[ERR_DLG_OPEN_QUIT], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return;
}
else if (state->show_edit)
@@ -178,11 +183,33 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
}
if (state->edit_info_focused)
- strcpy(state->error, errors[ERR_DLG_FOCUS_EDIT]);
+ {
+ if (strlcpy(state->error, errors[ERR_DLG_FOCUS_EDIT], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+ }
else if (state->show_edit || state->show_search)
- strcpy(state->error, errors[ERR_UNKNOWN_KEY]);
+ {
+ if (strlcpy(state->error, errors[ERR_UNKNOWN_KEY], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+ }
else
- strcpy(state->error, errors[ERR_UNKNOWN_KEY_HELP]);
+ {
+ if (strlcpy(state->error, errors[ERR_UNKNOWN_KEY_HELP],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+ }
}
int
@@ -661,8 +688,12 @@ cancel_close(struct DrawState* state)
cancel_msgstr(state);
else if (state->show_search)
cancel_search(state);
- else
- strcpy(state->error, errors[ERR_EXIT_KEY]);
+ else if (strlcpy(state->error, errors[ERR_EXIT_KEY], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
@@ -673,7 +704,12 @@ cancel_msgstr(struct DrawState* state)
if (!state->in_prompt && state->dirty)
{
state->in_prompt = 1;
- strcpy(state->prompt, prompt_cancel_dirty);
+ if (strlcpy(state->prompt, prompt_cancel_dirty, MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->prompt_callback = cancel_callback;
return 0;
}
@@ -727,14 +763,25 @@ copy_msgid_to_input(struct DrawState* state)
if (!state->in_prompt && *state->input_buffer->text)
{
state->in_prompt = 1;
- strcpy(state->prompt, prompt_overwrite);
+ if (strlcpy(state->prompt, prompt_overwrite, MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->prompt_callback = overwrite_copy_msgid_callback;
return 0;
}
if (state->msgid_number == 1)
{
- strcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST]);
+ if (strlcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
@@ -896,7 +943,13 @@ erase_forward(struct DrawState* state)
{
if (!join_lines(state, state->input_row, 1))
{
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
}
}
@@ -1096,13 +1149,23 @@ exit_program(struct DrawState* state)
{
if (state->show_edit)
{
- strcpy(state->error, errors[ERR_DLG_OPEN]);
+ if (strlcpy(state->error, errors[ERR_DLG_OPEN], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
if (state->dirty)
{
state->in_prompt = 1;
- strcpy(state->prompt, prompt_dirty);
+ if (strlcpy(state->prompt, prompt_dirty, MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->prompt_callback = quit_callback;
}
else
@@ -1132,7 +1195,12 @@ insert_line(struct DrawState* state)
state->input_rows_count * sizeof(struct BufferLine));
if (!newbuf)
{
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
return 0;
}
@@ -1142,7 +1210,12 @@ insert_line(struct DrawState* state)
uint32_t* newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
if (!newtext)
{
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
return 0;
}
@@ -1723,14 +1796,25 @@ paste_paste_buffer_to_input(struct DrawState* state)
if (!state->in_prompt && *state->input_buffer->text)
{
state->in_prompt = 1;
- strcpy(state->prompt, prompt_overwrite);
+ if (strlcpy(state->prompt, prompt_overwrite, MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->prompt_callback = overwrite_paste_callback;
return 0;
}
if (state->msgid_number == 1)
{
- strcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST]);
+ if (strlcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
@@ -1855,7 +1939,13 @@ save_msgstr(struct DrawState* state)
to_save = calloc(to_save_size, sizeof(uint32_t));
if (!to_save)
{
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
struct BufferLine* pinput_buffer = NULL;
@@ -1902,7 +1992,12 @@ show_edit(struct DrawState* state)
{
if (!load_msgstr(state) || !load_info(state))
{
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
return 0;
}
@@ -1950,7 +2045,13 @@ toggle_fuzzy(struct DrawState* state)
{
if (state->msgid_number == 1)
{
- strcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST]);
+ if (strlcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
if (state->msgid_count > 0)
@@ -1992,7 +2093,13 @@ yank_input_to_paste_buffer(struct DrawState* state)
if (state->msgid_number == 1)
{
- strcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST]);
+ if (strlcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return 0;
}
@@ -2068,15 +2175,30 @@ write_file(struct DrawState* state)
switch (result)
{
case SAVE_ERR_CANT_ALLOC:
- strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state->error, errors[ERR_CANT_ALLOC], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
break;
case SAVE_ERR_CANT_OPEN_FILE:
- strcpy(state->error, errors[ERR_CANT_SAVE]);
+ if (strlcpy(state->error, errors[ERR_CANT_SAVE], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
break;
case SAVE_ERR_CANT_MOVE_FILE:
- strcpy(state->error, strerror(errno));
+ if (strlcpy(state->error, strerror(errno), MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
break;
default:
@@ -2205,7 +2327,13 @@ main(int argc, char** argv)
state.maxy = tb_height();
if (!draw(&state))
- strcpy(state.error, errors[ERR_CANT_ALLOC]);
+ if (strlcpy(state.error, errors[ERR_CANT_ALLOC],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
tb_present();
result = tb_poll_event(&ev);
if (result == TB_OK && ev.type == TB_EVENT_RESIZE)
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/util.c b/util.c
@@ -12,6 +12,12 @@
#include "po.h"
#include "util.h"
+enum { UTLERRNONE = 0, UTLERROVFL = 1 };
+
+int utlerrno = UTLERRNONE;
+
+/* max - max Unicode characters to convert from UTF-8
+ * Returns: number of processed Unicode characters */
size_t
u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
{
@@ -36,12 +42,16 @@ u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
return added;
}
+/* max - max Unicode characters to convert to UTF-8
+ * Returns: number of processed Unicode characters */
size_t
-unicode_string_to_u8(char* s, const uint32_t* us, const size_t max)
+unicode_string_to_u8(char* s, const size_t s_size, const uint32_t* us,
+ const size_t max)
{
char ch[8];
const uint32_t* pus = us;
- size_t added = 0;
+ size_t len;
+ size_t added = 0;
if (!pus)
return added;
@@ -49,13 +59,22 @@ unicode_string_to_u8(char* s, const uint32_t* us, const size_t max)
*s = 0;
while (*pus)
{
- int len = tb_utf8_unicode_to_char(ch, *pus);
- if (added + 1 > max)
- break;
- strncat(s, ch, len);
+ size_t res;
+
+ len = tb_utf8_unicode_to_char(ch, *pus);
+ ch[len] = 0;
+ res = strlcat(s, ch, s_size);
+ if (res >= s_size)
+ {
+ utlerrno = UTLERROVFL;
+ return added;
+ }
added++;
pus++;
+ if (added + 1 > max)
+ break;
}
+ utlerrno = UTLERRNONE;
return added;
}
@@ -68,7 +87,7 @@ u32_match_msgid_ending(const uint32_t* msgid, uint32_t* msgstr, size_t max)
size_t buf_len = 0;
size_t msgid_len = 0;
- buf_len = u32_strcpy(buf, msgstr);
+ buf_len = u32_strncpy(buf, msgstr, (max + 1) * sizeof(uint32_t));
msgid_len = u32_strlen(msgid);
if (msgid_len > 1
@@ -251,25 +270,13 @@ u32_strchr(const uint32_t* haystack, const uint32_t needle)
}
size_t
-u32_strcpy(uint32_t* to, const uint32_t* from)
-{
- const uint32_t* pfrom = from;
- size_t copied = 0;
- while (*pfrom)
- {
- *to++ = *pfrom++;
- copied++;
- }
- *to = 0;
- return copied;
-}
-
-size_t
u32_strncpy(uint32_t* to, const uint32_t* from, size_t max)
{
const uint32_t* pfrom = from;
size_t copied = 0;
- while (*pfrom && copied < max - 1)
+ /* pfrom - from < max - 1 ... except we can't reliably subtract with
+ * size_t */
+ while (*pfrom && pfrom + 1 < max + from)
{
*to++ = *pfrom++;
copied++;
@@ -287,12 +294,12 @@ u32_strncat(uint32_t* to, const uint32_t* from, size_t max)
{
const uint32_t* pfrom = from;
size_t copied = 0;
- while (*to)
+ while (*to && copied + 1 < max)
{
to++;
copied++;
}
- while (*pfrom && copied < max - 1)
+ while (*pfrom && copied + 1 < max)
{
*to++ = *pfrom++;
copied++;
@@ -304,11 +311,12 @@ u32_strncat(uint32_t* to, const uint32_t* from, size_t max)
size_t
u32_u8_strncpy(uint32_t* to, const char* from, size_t max)
{
- uint32_t* ufrom = calloc(strlen(from) + 1, sizeof(uint32_t));
+ uint32_t* ufrom = calloc(max + 1, sizeof(uint32_t));
+ size_t len;
if (!ufrom)
return 0;
u8_string_to_unicode(ufrom, from, max);
- size_t len = u32_strncpy(to, ufrom, max);
+ len = u32_strncpy(to, ufrom, max);
free(ufrom);
return len;
}
@@ -316,14 +324,17 @@ u32_u8_strncpy(uint32_t* to, const char* from, size_t max)
size_t
u8_u32_strncpy(char* to, const uint32_t* from, size_t max)
{
- char* cfrom = calloc(u32_strlen(from) * UTF8REPMAX + 1, 1);
+ char* cfrom = calloc(max + 1, 1);
+ size_t len;
if (!cfrom)
return 0;
- unicode_string_to_u8(cfrom, from, max);
+ unicode_string_to_u8(cfrom, max + 1, from, max);
+ len = strlen(cfrom);
strncpy(to, cfrom, max);
- to[max - 1] = 0;
+ if (len && len < max)
+ to[len] = 0;
free(cfrom);
- return strlen(to);
+ return len;
}
/* wrap - if >0, also wrap lines
@@ -455,9 +466,10 @@ u32_starts_with(const uint32_t* s, const uint32_t* with)
const char*
u8_basename(const char* path)
{
+ const char* ppath;
if (!path)
return NULL;
- const char* ppath = path + strlen(path);
+ ppath = path + strlen(path);
while (ppath != path && *ppath != '/')
ppath--;
if (*ppath == '/')
@@ -465,6 +477,7 @@ u8_basename(const char* path)
return ppath;
}
+/*
void
poe_log(const char* msg, ...)
{
@@ -474,4 +487,4 @@ poe_log(const char* msg, ...)
vfprintf(log, msg, args);
va_end(args);
fclose(log);
-}
+}*/
diff --git a/util.h b/util.h
@@ -25,6 +25,7 @@ enum {
};
#define MAXBUFLINE 4096
+#define MAXCOPYBUF 8192
#define MAXDATEBUF 80
#define MAXFLAGSBUF (4 + 1)
#define MAXMSGLINE 1024
@@ -33,8 +34,18 @@ enum {
/* maximum chars for UTF-8 representations of Unicode chars, per Unicode char */
#define UTF8REPMAX 6
+extern int utlerrno;
+
+#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
+
size_t u8_string_to_unicode(uint32_t* us, const char* s, const size_t max);
-size_t unicode_string_to_u8(char* s, const uint32_t* us, const size_t max);
+size_t unicode_string_to_u8(char* s, const size_t s_size, const uint32_t* us,
+ const size_t max);
size_t u32_match_msgid_ending(const uint32_t* msgid, uint32_t* msgstr,
size_t max);
size_t u32_count_chars(const uint32_t* s, const uint32_t ch);
@@ -44,7 +55,6 @@ size_t u32_decode_tabs(uint32_t* s, size_t max);
size_t u32_strlen(const uint32_t* s);
const uint32_t* u32_strstr(const uint32_t* haystack, const uint32_t* needle);
const uint32_t* u32_strchr(const uint32_t* haystack, const uint32_t needle);
-size_t u32_strcpy(uint32_t* to, const uint32_t* from);
size_t u32_strncpy(uint32_t* to, const uint32_t* from, size_t max);
size_t u32_strncat(uint32_t* to, const uint32_t* from, size_t max);
size_t u32_u8_strncpy(uint32_t* to, const char* from, size_t max);
@@ -58,4 +68,4 @@ const int u32_is_word_boundary(const uint32_t ch, const int strictly_whitespace)
const int starts_with(const char* s, const char* with);
const int u32_starts_with(const uint32_t* s, const uint32_t* with);
const char* u8_basename(const char* path);
-void poe_log(const char* msg, ...);
+/*void poe_log(const char* msg, ...);*/