diff --git a/bootstrap.conf b/bootstrap.conf index cec2464..456f4f1 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -65,6 +65,7 @@ size_max ssize_t stat-time stdbool +stdckdint stdlib symlinkat sys_stat diff --git a/src/patch.c b/src/patch.c index 06523e1..ff12801 100644 --- a/src/patch.c +++ b/src/patch.c @@ -711,7 +711,7 @@ main (int argc, char **argv) { if (! written_to_rejname) { - copy_file (TMPREJNAME, rejname, 0, 0, + copy_file (TMPREJNAME, NULL, rejname, NULL, 0, S_IFREG | 0666, true); written_to_rejname = true; } diff --git a/src/pch.c b/src/pch.c index 21ef0b2..3d78cd1 100644 --- a/src/pch.c +++ b/src/pch.c @@ -2482,7 +2482,7 @@ do_ed_script (char const *input_name, char const *output_name, if (inerrno != ENOENT) { *outname_needs_removal = true; - copy_file (input_name, output_name, 0, exclusive, + copy_file (input_name, &instat, output_name, NULL, exclusive, instat.st_mode, true); } fflush (stdout); diff --git a/src/util.c b/src/util.c index 9b38b6c..716d142 100644 --- a/src/util.c +++ b/src/util.c @@ -39,13 +39,14 @@ #endif #include +#include + #include #include #if USE_XATTR # include # include -# include #endif #include @@ -317,7 +318,7 @@ static void create_backup_copy (char const *from, char const *to, const struct stat *st, bool to_dir_known_to_exist) { - copy_file (from, to, NULL, 0, st->st_mode, to_dir_known_to_exist); + copy_file (from, st, to, NULL, 0, st->st_mode, to_dir_known_to_exist); set_file_attributes (to, FA_TIMES | FA_IDS | FA_MODE, from, st, st->st_mode, NULL); } @@ -471,15 +472,23 @@ move_file (char const *from, bool *from_needs_removal, /* FROM contains the contents of the symlink we have patched; need to convert that back into a symlink. */ - char *buffer = xmalloc (PATH_MAX); - int fd, size = 0, i; + idx_t alloc; + if (ckd_add (&alloc, fromst->st_size, 1)) + xalloc_die (); + char *buffer = ximalloc (alloc); - if ((fd = safe_open (from, O_RDONLY | O_BINARY, 0)) < 0) + int fd = safe_open (from, O_RDONLY | O_BINARY, 0); + if (fd < 0) pfatal ("Can't reopen file %s", quotearg (from)); - while ((i = read (fd, buffer + size, PATH_MAX - size)) > 0) + + ssize_t i; + idx_t size = 0; + while (0 < (i = read (fd, buffer + size, alloc - size))) size += i; if (i != 0 || close (fd) != 0) read_fatal (); + if (size == alloc) + fatal ("file %s grew", quotearg (from)); buffer[size] = 0; if (! backup) @@ -528,7 +537,8 @@ move_file (char const *from, bool *from_needs_removal, else if (errno != ENOENT) pfatal ("Can't remove file %s", quotearg (to)); } - copy_file (from, to, &tost, 0, mode, to_dir_known_to_exist); + copy_file (from, fromst, to, &tost, 0, mode, + to_dir_known_to_exist); insert_file_id (&tost, CREATED); return; } @@ -612,7 +622,8 @@ copy_to_fd (const char *from, int tofd) /* Copy a file. */ void -copy_file (char const *from, char const *to, struct stat *tost, +copy_file (char const *from, struct stat const *fromst, + char const *to, struct stat *tost, int to_flags, mode_t mode, bool to_dir_known_to_exist) { int tofd; @@ -624,11 +635,16 @@ copy_file (char const *from, char const *to, struct stat *tost, if (S_ISLNK (mode)) { - char *buffer = xmalloc (PATH_MAX + 1); - ssize_t r; + idx_t alloc; + if (ckd_add (&alloc, fromst->st_size, 1)) + xalloc_die (); + char *buffer = ximalloc (alloc); + ssize_t r = safe_readlink (from, buffer, alloc); - if ((r = safe_readlink (from, buffer, PATH_MAX)) < 0) - pfatal ("Can't read %s %s", "symbolic link", from); + if (r < 0) + pfatal ("Can't read symbolic link %s", from); + if (r == alloc) + fatal ("symbolic link %s grew", quotearg (from)); buffer[r] = '\0'; if (safe_symlink (buffer, to) != 0) pfatal ("Can't create %s %s", "symbolic link", to); diff --git a/src/util.h b/src/util.h index 71e219c..f3a8d8a 100644 --- a/src/util.h +++ b/src/util.h @@ -49,7 +49,8 @@ int create_file (char const *, int, mode_t, bool); int systemic (char const *); char *format_linenum (char[LINENUM_LENGTH_BOUND + 1], lin); void Fseek (FILE *, file_offset, int); -void copy_file (char const *, char const *, struct stat *, int, mode_t, bool); +void copy_file (char const *, struct stat const *, + char const *, struct stat *, int, mode_t, bool); void append_to_file (char const *, char const *); void exit_with_signal (int) __attribute__ ((noreturn)); void ignore_signals (void);