чување 5cc50247e21f89af398eb94693d70f30c83e7580
родитељ cec2b429688d1cf8995d8675aee116801fe55513
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sat, 2 Mar 2024 22:46:28 +0100
Switch from strcpy,strcat to strlcpy,strlcat
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 2 | -- |
| M | TODO.done | | | 2 | ++ |
| M | sled.c | | | 331 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
| A | strlcat.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | strlcpy.c | | | 49 | +++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | util.c | | | 83 | +++++++++++++++++++++++++++++++------------------------------------------------ |
| M | util.h | | | 10 | +++++----- |
измењених датотека: 7, додавања: 399(+), брисања: 132(-)
diff --git a/TODO b/TODO
@@ -3,8 +3,6 @@ TODO
[~] Code optimization (struct coord...)
-[ ] Switch to strlcpy, strlcat; check u8_*/u32_*
-
Legend
------
diff --git a/TODO.done b/TODO.done
@@ -1,6 +1,8 @@
Done or canceled todos
======================
+[x] Switch to strlcpy, strlcat; check u8_*/u32_*
+
[x] Change the backup method, as `crontab -e` doesn't like inode changes
(crontab -e with CREATE_BACKUPS gives:
diff --git a/sled.c b/sled.c
@@ -59,6 +59,13 @@ extern const char* prompt_overwrite;
extern const char* prompt_reread_dirty;
extern const char* program_name;
+#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
+
int clear_selection(struct DrawState* state);
int cp(const char* from, const char* to);
int create_file(struct DrawState* dstate);
@@ -203,7 +210,11 @@ dirname(char* path)
result = malloc(MAXPATH);
memset(result, 0, MAXPATH);
- strcpy(result, path);
+ if (strlcpy(result, path, MAXPATH) >= MAXPATH)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
p = result + strlen(result) - 1;
if (*p == '/')
*p = 0;
@@ -240,8 +251,8 @@ do_search_replace(struct DrawState* state)
{
state->dirty = 1;
*found = 0;
- u32_strcat(buf, before);
- u32_strcat(buf, state->input);
+ u32_strncat(buf, before, MAXBUFLINE);
+ u32_strncat(buf, state->input, MAXBUFLINE);
before = found + search_len;
found = (uint32_t*)u32_strstr(before, state->search);
if (found)
@@ -250,9 +261,9 @@ do_search_replace(struct DrawState* state)
after = before;
}
if (state->buffer[row].text + state->buffer[row].length > after)
- u32_strcat(buf, after);
+ u32_strncat(buf, after, MAXBUFLINE);
- u32_strcpy(state->buffer[row].text, buf);
+ u32_strncpy(state->buffer[row].text, buf, MAXBUFLINE);
state->buffer[row].length = u32_strlen(buf);
}
return 0;
@@ -277,10 +288,10 @@ erase_selection(struct DrawState* state)
get_selection(&ssr, &ssc, &ser, &sec, state);
- u32_strcpy(buf, state->buffer[ser].text + sec);
+ u32_strncpy(buf, state->buffer[ser].text + sec, MAXBUFLINE);
*(state->buffer[ssr].text + ssc) = 0;
- u32_strcat(state->buffer[ssr].text, buf);
+ u32_strncat(state->buffer[ssr].text, buf, MAXBUFLINE);
state->buffer[ssr].length = u32_strlen(state->buffer[ssr].text);
if (ssr != ser)
@@ -288,8 +299,9 @@ erase_selection(struct DrawState* state)
for (size_t row = 0; ser + row + 1 < state->rows_count;
row++)
{
- u32_strcpy(state->buffer[ssr + row + 1].text,
- state->buffer[ser + row + 1].text);
+ u32_strncpy(state->buffer[ssr + row + 1].text,
+ state->buffer[ser + row + 1].text,
+ MAXBUFLINE);
state->buffer[ssr + row + 1].length
= state->buffer[ser + row + 1].length;
}
@@ -373,7 +385,13 @@ go_to_line_callback(struct DrawState* state)
u8_input = calloc(len + 1, UTF8REPMAX);
if (!u8_input)
{
- 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;
}
@@ -381,7 +399,13 @@ go_to_line_callback(struct DrawState* state)
errno = 0;
lineno = strtoul(u8_input, NULL, 10);
if (errno)
- strcpy(state->error, errors[ERR_INVALID_NUM]);
+ if (strlcpy(state->error, errors[ERR_INVALID_NUM],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
if (!*state->error)
{
if (lineno > state->rows_count - 1)
@@ -447,8 +471,13 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
&& strchr("0123456789", (const char)ev->ch))
|| !IN(state->mode, M_INPUT_NUM))
input_insert_char(state, ev->ch);
- else
- strcpy(state->error, errors[ERR_INPUT_NONNUM]);
+ else if (strlcpy(state->error, errors[ERR_INPUT_NONNUM],
+ MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
return;
}
}
@@ -465,7 +494,12 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
if (IN(state->mode, M_HELP))
{
- 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;
}
@@ -513,7 +547,12 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
}
}
- 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);
+ }
}
int
@@ -711,7 +750,13 @@ load_file(struct DrawState* state, long* lineno, long* col)
newchunk[row].text = newtext;
}
- strcpy(state->action, actions[ACT_READING]);
+ if (strlcpy(state->action, actions[ACT_READING], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+
redraw_status(state);
state->buffer = newchunk;
@@ -757,8 +802,9 @@ load_file(struct DrawState* state, long* lineno, long* col)
}
line = state->buffer + state->buffer_size - ALLOC_DELTA;
}
- line = state->buffer + state->rows_count;
- line->length = u32_u8_strcpy(line->text, input_line);
+ line = state->buffer + state->rows_count;
+ line->length
+ = u32_u8_strncpy(line->text, input_line, MAXBUFLINE);
state->rows_count++;
}
fclose(input);
@@ -876,7 +922,7 @@ print_error(const int code, const char* msg, ...)
char buf[MAXBUFLINE];
va_list args;
va_start(args, msg);
- vsnprintf(buf, sizeof(buf), msg, args);
+ vsnprintf(buf, MAXBUFLINE, msg, args);
va_end(args);
fprintf(stderr, "%s: %s\n", program_name, buf);
return code;
@@ -908,11 +954,21 @@ reread_file(struct DrawState* state)
switch (result)
{
case LOAD_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 LOAD_ERR_CANT_OPEN_FILE:
- strcpy(state->error, errors[ERR_CANT_OPEN]);
+ if (strlcpy(state->error, errors[ERR_CANT_OPEN], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
break;
default:;
@@ -943,7 +999,12 @@ save_file(struct DrawState* state)
if (!(buf = calloc(MAXBUFLINE, 1)))
return SAVE_ERR_CANT_ALLOC;
- strcpy(state->action, actions[ACT_WRITING]);
+ if (strlcpy(state->action, actions[ACT_WRITING], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
redraw_status(state);
errno = 0;
@@ -1054,7 +1115,7 @@ search_replace_replace_dialog_callback(struct DrawState* state)
void
search_update_callback(struct DrawState* state)
{
- u32_strcpy(state->search, state->input);
+ u32_strncpy(state->search, state->input, MAXBUFLINE);
}
int
@@ -1065,8 +1126,12 @@ cancel_close(struct DrawState* state)
{
if (SEL_NOT_EMPTY(state))
clear_selection(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);
+ }
}
else
{
@@ -1193,8 +1258,8 @@ erase_line(struct DrawState* state)
for (size_t row = state->coord.row; row < state->rows_count - 1; row++)
{
current = state->buffer + row;
- current->length = u32_strcpy(current->text,
- state->buffer[row + 1].text);
+ current->length = u32_strncpy(current->text,
+ state->buffer[row + 1].text, MAXBUFLINE);
}
*state->buffer[state->rows_count - 1].text = 0;
state->buffer[state->rows_count - 1].length = 0;
@@ -1290,7 +1355,12 @@ exit_program(struct DrawState* state)
if (state->dirty)
{
SET(state->mode, M_PROMPT);
- 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
@@ -1383,7 +1453,7 @@ input_erase_to_end(struct DrawState* state)
{
state->input[state->input_column] = 0;
input_move_end(state);
- u32_strcpy(state->search, state->input);
+ u32_strncpy(state->search, state->input, MAXBUFLINE);
if (state->input_update_callback)
state->input_update_callback(state);
return 0;
@@ -1762,16 +1832,21 @@ paste_from_paste(struct DrawState* state)
if (!newtext)
{
state->running = 0;
- 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);
+ }
goto paste_from_paste_cleanup;
}
u32_strncpy(newtext, line->text, state->coord.col + 1);
- u32_strcat(newtext, state->paste[0].text);
+ u32_strncat(newtext, state->paste[0].text, MAXBUFLINE);
if (state->paste_count == 1)
{
- u32_strcat(newtext, line->text + state->coord.col);
- line->length = u32_strcpy(line->text, newtext);
+ u32_strncat(newtext, line->text + state->coord.col, MAXBUFLINE);
+ line->length = u32_strncpy(line->text, newtext, MAXBUFLINE);
state->coord.col += state->paste[state->paste_count - 1].length;
}
else
@@ -1781,33 +1856,41 @@ paste_from_paste(struct DrawState* state)
if (!rest)
{
state->running = 0;
- 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);
+ }
goto paste_from_paste_cleanup;
}
- u32_strcpy(rest, line->text + state->coord.col);
- line->length = u32_strcpy(line->text, newtext);
+ u32_strncpy(rest, line->text + state->coord.col, MAXBUFLINE);
+ line->length = u32_strncpy(line->text, newtext, MAXBUFLINE);
for (size_t row = state->rows_count - state->coord.row
- (state->paste_count - 2) - 1;
row > 0; row--)
{
line = state->buffer + state->coord.row
+ state->paste_count - 2 + row;
- line->length = u32_strcpy(line->text,
- state->buffer[state->coord.row + row - 1].text);
+ line->length = u32_strncpy(line->text,
+ state->buffer[state->coord.row + row - 1].text,
+ MAXBUFLINE);
}
line = state->buffer + state->coord.row;
- line->length = u32_strcpy(line->text, newtext);
+ line->length = u32_strncpy(line->text, newtext, MAXBUFLINE);
for (size_t row = 1; row < state->paste_count - 1; row++)
{
line = state->buffer + state->coord.row + row;
- line->length = u32_strcpy(line->text,
- state->paste[row].text);
+ line->length = u32_strncpy(line->text,
+ state->paste[row].text, MAXBUFLINE);
}
line = state->buffer + state->coord.row + state->paste_count
- 1;
- u32_strcpy(newtext, state->paste[state->paste_count - 1].text);
- u32_strcat(newtext, rest);
- line->length = u32_strcpy(line->text, newtext);
+ u32_strncpy(newtext, state->paste[state->paste_count - 1].text,
+ MAXBUFLINE);
+ u32_strncat(newtext, rest, MAXBUFLINE);
+ line->length = u32_strncpy(line->text, newtext, MAXBUFLINE);
state->coord.col = state->paste[state->paste_count - 1].length;
state->coord.row += state->paste_count - 1;
}
@@ -1875,7 +1958,12 @@ reread_or_callback(struct DrawState* state)
if (state->dirty)
{
SET(state->mode, M_PROMPT);
- strcpy(state->prompt, prompt_reread_dirty);
+ if (strlcpy(state->prompt, prompt_reread_dirty, MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->prompt_callback = reread_callback;
}
else
@@ -1893,7 +1981,13 @@ show_go_to_line(struct DrawState* state)
if (!(state->input = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -1915,7 +2009,13 @@ show_replace(struct DrawState* state)
if (!(state->input = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -1935,7 +2035,13 @@ show_search(struct DrawState* state)
if (!(state->search = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -1948,7 +2054,13 @@ show_search(struct DrawState* state)
if (!(state->input = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -1968,7 +2080,13 @@ show_search_replace(struct DrawState* state)
if (!(state->search = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -1981,7 +2099,13 @@ show_search_replace(struct DrawState* state)
if (!(state->input = calloc(MAXINPUT, sizeof(uint32_t))))
{
state->running = 0;
- 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;
}
}
@@ -2017,7 +2141,13 @@ simple_insert_line(struct DrawState* state)
if (!newchunk)
{
state->running = 0;
- 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;
}
state->buffer = newchunk;
@@ -2030,7 +2160,14 @@ simple_insert_line(struct DrawState* state)
if (!newtext)
{
state->running = 0;
- 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;
}
line->text = newtext;
@@ -2039,11 +2176,12 @@ simple_insert_line(struct DrawState* state)
}
state->rows_count++;
for (size_t i = state->rows_count - 1; i > state->coord.row + 1; i--)
- state->buffer[i].length = u32_strcpy(state->buffer[i].text,
- state->buffer[i - 1].text);
+ state->buffer[i].length = u32_strncpy(state->buffer[i].text,
+ state->buffer[i - 1].text, MAXBUFLINE);
state->buffer[state->coord.row + 1].length
- = u32_strcpy(state->buffer[state->coord.row + 1].text,
- state->buffer[state->coord.row].text + state->coord.col);
+ = u32_strncpy(state->buffer[state->coord.row + 1].text,
+ state->buffer[state->coord.row].text + state->coord.col,
+ MAXBUFLINE);
state->buffer[state->coord.row].text[state->coord.col] = 0;
state->buffer[state->coord.row].length = state->coord.col;
state->dirty = 1;
@@ -2057,13 +2195,14 @@ simple_join_lines(struct DrawState* state)
if (first_line == state->rows_count - 1)
return;
- u32_strcat(state->buffer[first_line].text,
- state->buffer[first_line + 1].text);
+ u32_strncat(state->buffer[first_line].text,
+ state->buffer[first_line + 1].text, MAXBUFLINE);
state->buffer[first_line].length
= u32_strlen(state->buffer[first_line].text);
for (size_t i = first_line + 1; i < state->rows_count - 1; i++)
{
- u32_strcpy(state->buffer[i].text, state->buffer[i + 1].text);
+ u32_strncpy(state->buffer[i].text, state->buffer[i + 1].text,
+ MAXBUFLINE);
state->buffer[i].length = state->buffer[i + 1].length;
}
*state->buffer[state->rows_count - 1].text = 0;
@@ -2123,7 +2262,13 @@ simple_yank(struct DrawState* state)
if (!newtext)
{
state->running = 0;
- 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);
+ }
}
newbuf[row].text = newtext;
newbuf[row].length = 0;
@@ -2134,12 +2279,13 @@ simple_yank(struct DrawState* state)
state->buffer[ssr].text + ssc, sec - ssc + 1);
else
{
- state->paste[0].length = u32_strcpy(state->paste[0].text,
- state->buffer[ssr].text + ssc);
+ state->paste[0].length = u32_strncpy(state->paste[0].text,
+ state->buffer[ssr].text + ssc, MAXBUFLINE);
for (size_t row = 1; row < state->paste_count - 1; row++)
state->paste[row].length
- = u32_strcpy(state->paste[row].text,
- state->buffer[ssr + row].text);
+ = u32_strncpy(state->paste[row].text,
+ state->buffer[ssr + row].text,
+ MAXBUFLINE);
state->paste[state->paste_count - 1].length
= u32_strncpy(state->paste[state->paste_count - 1].text,
state->buffer[ser].text, sec + 1);
@@ -2200,22 +2346,42 @@ 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_COPY_FILE:
- strcpy(state->error, errors[ERR_CANT_COPY]);
+ if (strlcpy(state->error, errors[ERR_CANT_COPY], MAXBUFLINE)
+ >= MAXBUFLINE)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
state->running = 0;
break;
case SAVE_ERR_CANT_READLINK:
case SAVE_ERR_CANT_STAT_FILE:
case SAVE_ERR_CANT_SYMLINK:
case SAVE_ERR_CANT_UNLINK:
- 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;
case SAVE_ERR_NONE:
@@ -2358,10 +2524,21 @@ main(int argc, char** argv)
/* Backup filename is the target file + suffix if the file to
* write is a symlink, otherwise file + suffix */
- strcpy(state.backup_filename,
- state.rfn_len > 0 ? state.real_filename
- : state.filename);
- strcat(state.backup_filename, backup_suffix);
+ if (strlcpy(state.backup_filename,
+ state.rfn_len > 0 ? state.real_filename
+ : state.filename,
+ MAXPATH)
+ >= MAXPATH)
+ {
+ print_error(1, "strlcpy:%d: Overflow", __LINE__);
+ exit(1);
+ }
+ if (strlcat(state.backup_filename, backup_suffix, MAXPATH)
+ >= MAXPATH)
+ {
+ print_error(1, "strlcat:%d: Overflow", __LINE__);
+ exit(1);
+ }
#ifdef __OpenBSD__
if (unveil(state.backup_filename, "rwc") < 0)
{
@@ -2465,7 +2642,13 @@ init_termbox:
if (!draw(&state))
{
state.running = 0;
- 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);
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
@@ -10,6 +10,10 @@
#include "termbox.h"
#include "util.h"
+enum { UTLERRNONE = 0, UTLERROVFL = 1 };
+
+int utlerrno = UTLERRNONE;
+
size_t
u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
{
@@ -34,12 +38,15 @@ u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
return added;
}
+/* If the textual representation of characters in us exceeds max, utlerrno is
+ * set to UTLERROVFL */
size_t
unicode_string_to_u8(char* s, 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;
@@ -47,13 +54,19 @@ 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)
+ len = tb_utf8_unicode_to_char(ch, *pus);
+ if (added + 1 >= max)
break;
- strncat(s, ch, len);
+ ch[len] = 0;
+ if (strlcat(s, ch, max) >= max)
+ {
+ utlerrno = UTLERROVFL;
+ return added;
+ }
added++;
pus++;
}
+ utlerrno = UTLERRNONE;
return added;
}
@@ -120,25 +133,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)
+u32_strncpy(uint32_t* to, const uint32_t* from, const 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++;
@@ -149,41 +150,19 @@ u32_strncpy(uint32_t* to, const uint32_t* from, size_t max)
/*
* to - u32 string to concatenate to
+ * max - total combined string size
* from - u32 string to concatenate */
size_t
-u32_strcat(uint32_t* to, const uint32_t* from)
-{
- const uint32_t* pfrom = from;
- size_t copied = 0;
- while (*to)
- {
- to++;
- copied++;
- }
- while (*pfrom)
- {
- *to++ = *pfrom++;
- copied++;
- }
- *to = 0;
- return copied;
-}
-
-/*
- * to - u32 string to concatenate to
- * from - u32 string to concatenate
- * max - total combined string size */
-size_t
-u32_strncat(uint32_t* to, const uint32_t* from, size_t max)
+u32_strncat(uint32_t* to, const uint32_t* from, const 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++;
@@ -193,13 +172,14 @@ u32_strncat(uint32_t* to, const uint32_t* from, size_t max)
}
size_t
-u32_u8_strcpy(uint32_t* to, const char* from)
+u32_u8_strncpy(uint32_t* to, const char* from, const 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, strlen(from));
- size_t len = u32_strcpy(to, ufrom);
+ u8_string_to_unicode(ufrom, from, max);
+ len = u32_strncpy(to, ufrom, max);
free(ufrom);
return len;
}
@@ -248,9 +228,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 == '/')
diff --git a/util.h b/util.h
@@ -47,6 +47,8 @@ enum { ACT_WRITING, ACT_READING };
#define UTF8REPMAX 6
#define TB_KEY_CTRL_SPACE 0x00
+extern int utlerrno;
+
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 u32_strlen(const uint32_t* s);
@@ -54,11 +56,9 @@ const uint32_t* u32_strstr(const uint32_t* haystack, const uint32_t* needle);
const uint32_t* u32_strrstr(const uint32_t* haystack, const uint32_t* needle,
const uint32_t* haystack_tail);
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_strcat(uint32_t* to, const uint32_t* from);
-size_t u32_strncat(uint32_t* to, const uint32_t* from, size_t max);
-size_t u32_u8_strcpy(uint32_t* to, const char* from);
+size_t u32_strncpy(uint32_t* to, const uint32_t* from, const size_t max);
+size_t u32_strncat(uint32_t* to, const uint32_t* from, const size_t max);
+size_t u32_u8_strncpy(uint32_t* to, const char* from, const size_t max);
const int is_word_boundary(const char ch, const int strictly_whitespace);
const int u32_is_word_boundary(const uint32_t ch, const int strictly_whitespace);
const int starts_with(const char* s, const char* with);