From 46e3e99b4870e3947a8851b1f4e54956cebc1846 Mon Sep 17 00:00:00 2001 From: yang_zhuang_zhuang <1162011203@qq.com> Date: Mon, 8 Feb 2021 17:11:21 +0800 Subject: [PATCH] backport patches from upstream --- backport-sed-c-flag.patch | 247 ++++++++++++++++++ ...ery-long-execution-lines-tiny-change.patch | 56 ++++ ...-long-input-lines-with-R-tiny-change.patch | 55 ++++ sed.spec | 12 +- 4 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 backport-sed-c-flag.patch create mode 100644 backport-sed-handle-very-long-execution-lines-tiny-change.patch create mode 100644 backport-sed-handle-very-long-input-lines-with-R-tiny-change.patch diff --git a/backport-sed-c-flag.patch b/backport-sed-c-flag.patch new file mode 100644 index 0000000..114d5c7 --- /dev/null +++ b/backport-sed-c-flag.patch @@ -0,0 +1,247 @@ +From f336bde91e3fd9c3c2960aa548b8917eb1216678 Mon Sep 17 00:00:00 2001 +From: Jakub Martisko +Date: Thu, 6 Feb 2020 15:26:33 +0100 +Subject: [PATCH] -c flag + +--- + sed/execute.c | 18 +++++++++-- + sed/sed.c | 20 +++++++++++- + sed/sed.h | 4 +++ + sed/utils.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ + sed/utils.h | 2 ++ + 5 files changed, 127 insertions(+), 3 deletions(-) + +diff --git a/sed/execute.c b/sed/execute.c +index c5f07cc..4e5f5b3 100644 +--- a/sed/execute.c ++++ b/sed/execute.c +@@ -670,11 +670,25 @@ closedown (struct input *input) + if (strcmp (in_place_extension, "*") != 0) + { + char *backup_file_name = get_backup_file_name (target_name); +- ck_rename (target_name, backup_file_name, input->out_file_name); ++ if (copy_instead_of_rename) ++ { ++ ck_fccopy (target_name, backup_file_name, input->out_file_name); ++ } ++ else ++ { ++ ck_rename (target_name, backup_file_name, input->out_file_name); ++ } + free (backup_file_name); + } + +- ck_rename (input->out_file_name, target_name, input->out_file_name); ++ if (copy_instead_of_rename) ++ { ++ ck_fcmove (input->out_file_name, target_name, input->out_file_name); ++ } ++ else ++ { ++ ck_rename (input->out_file_name, target_name, input->out_file_name); ++ } + cancel_cleanup (); + free (input->out_file_name); + } +diff --git a/sed/sed.c b/sed/sed.c +index 1ca5839..745159e 100644 +--- a/sed/sed.c ++++ b/sed/sed.c +@@ -67,6 +67,10 @@ bool debug = false; + /* How do we edit files in-place? (we don't if NULL) */ + char *in_place_extension = NULL; + ++/* Do we use copy or rename when in in-place edit mode? (boolean ++ + value, non-zero for copy, zero for rename).*/ ++int copy_instead_of_rename = 0; ++ + /* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ + char const *read_mode = "r"; + char const *write_mode = "w"; +@@ -170,6 +174,10 @@ Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\ + #endif + fprintf (out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\ + edit files in place (makes backup if SUFFIX supplied)\n")); ++ ++ fprintf(out, _(" -c, --copy\n\ ++ use copy instead of rename when shuffling files in -i mode\n")); ++ + #if O_BINARY + fprintf (out, _(" -b, --binary\n\ + open files in binary mode (CR+LFs are not" \ +@@ -214,7 +222,7 @@ specified, then the standard input is read.\n\ + int + main (int argc, char **argv) + { +-#define SHORTOPTS "bsnrzuEe:f:l:i::V:" ++#define SHORTOPTS "bcsnrzuEe:f:l:i::V:" + + enum { SANDBOX_OPTION = CHAR_MAX+1, + DEBUG_OPTION +@@ -228,6 +236,7 @@ main (int argc, char **argv) + {"file", 1, NULL, 'f'}, + {"in-place", 2, NULL, 'i'}, + {"line-length", 1, NULL, 'l'}, ++ {"copy", 0, NULL, 'c'}, + {"null-data", 0, NULL, 'z'}, + {"zero-terminated", 0, NULL, 'z'}, + {"quiet", 0, NULL, 'n'}, +@@ -306,6 +315,10 @@ main (int argc, char **argv) + follow_symlinks = true; + break; + ++ case 'c': ++ copy_instead_of_rename = true; ++ break; ++ + case 'i': + separate_files = true; + IF_LINT (free (in_place_extension)); +@@ -376,6 +389,11 @@ main (int argc, char **argv) + } + } + ++ if (copy_instead_of_rename && in_place_extension == NULL) ++ { ++ fprintf (stderr, _("Error: -c used without -i.\n")); ++ usage(4); ++ } + if (!the_program) + { + if (optind < argc) +diff --git a/sed/sed.h b/sed/sed.h +index 1c8e83a..0859e72 100644 +--- a/sed/sed.h ++++ b/sed/sed.h +@@ -236,6 +236,10 @@ extern countT lcmd_out_line_len; + /* How do we edit files in-place? (we don't if NULL) */ + extern char *in_place_extension; + ++/* Do we use copy or rename when in in-place edit mode? (boolean ++ value, non-zero for copy, zero for rename).*/ ++extern int copy_instead_of_rename; ++ + /* The mode to use to read and write files, either "rt"/"w" or "rb"/"wb". */ + extern char const *read_mode; + extern char const *write_mode; +diff --git a/sed/utils.c b/sed/utils.c +index 9576dd1..371d5a9 100644 +--- a/sed/utils.c ++++ b/sed/utils.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "binary-io.h" + #include "unlocked-io.h" +@@ -400,7 +401,92 @@ ck_rename (const char *from, const char *to, const char *unlink_if_fail) + panic (_("cannot rename %s: %s"), from, strerror (errno)); + } + ++/* Downstream -c related functions */ + ++/* Panic on failing unlink */ ++void ++ck_unlink (const char *name) ++{ ++ if (unlink (name) == -1) ++ panic (_("cannot remove %s: %s"), name, strerror (errno)); ++} ++ ++/* Attempt to unlink denoted file if operation rd failed. */ ++static int ++_unlink_if_fail (int rd,const char * unlink_if_fail) ++{ ++ if (rd == -1 && unlink_if_fail) ++ { ++ int save_errno = errno; ++ ck_unlink (unlink_if_fail); ++ errno = save_errno; ++ } ++ ++ return rd != -1; ++} ++ ++/* Copy contents between files. */ ++static int ++_copy (from, to) ++ const char *from, *to; ++{ ++ static char buf[4096]; ++ ++ FILE *infile, *outfile; ++ int c, retval = 0; ++ errno = 0; ++ ++ infile = fopen (from, "r"); ++ if (infile == NULL) ++ return -1; ++ ++ outfile = fopen (to, "w"); ++ if (outfile == NULL) ++ { ++ fclose (infile); ++ return -1; ++ } ++ ++ while (1) ++ { ++ size_t bytes_in = fread (buf, 1, sizeof (buf), infile); ++ size_t bytes_out; ++ if (bytes_in == 0) ++ { ++ if (ferror (infile)) ++ retval = -1; ++ break; ++ } ++ ++ bytes_out = fwrite (buf, 1, bytes_in, outfile); ++ if (bytes_out != bytes_in) ++ { ++ retval = -1; ++ break; ++ } ++ } ++ ++ fclose (outfile); ++ fclose (infile); ++ ++ return retval; ++} ++ ++/* Attempt to copy file contents between the files. */ ++void ++ck_fccopy (const char *from,const char *to, const char *unlink_if_fail) ++{ ++ if (!_unlink_if_fail (_copy (from, to), unlink_if_fail)) ++ panic (_("cannot copy %s to %s: %s"), from, to, strerror (errno)); ++ } ++ ++/* Copy contents between files, and then unlink the source. */ ++void ++ck_fcmove (const char *from, const char *to,const char *unlink_if_fail) ++{ ++ ck_fccopy (from, to, unlink_if_fail); ++ ck_unlink (from); ++} + + + /* Implement a variable sized buffer of `stuff'. We don't know what it is, +diff --git a/sed/utils.h b/sed/utils.h +index 47a029e..0aba107 100644 +--- a/sed/utils.h ++++ b/sed/utils.h +@@ -40,6 +40,8 @@ size_t ck_getdelim (char **text, size_t *buflen, char buffer_delimiter, + FILE * ck_mkstemp (char **p_filename, const char *tmpdir, const char *base, + const char *mode) _GL_ARG_NONNULL ((1, 2, 3, 4)); + void ck_rename (const char *from, const char *to, const char *unlink_if_fail); ++void ck_fccopy (const char *from, const char *to, const char *unlink_if_fail); ++void ck_fcmove (const char *from, const char *to, const char *unlink_if_fail); + + void *ck_malloc (size_t size); + void *ck_realloc (void *ptr, size_t size); +-- +2.24.1 + diff --git a/backport-sed-handle-very-long-execution-lines-tiny-change.patch b/backport-sed-handle-very-long-execution-lines-tiny-change.patch new file mode 100644 index 0000000..b3d8434 --- /dev/null +++ b/backport-sed-handle-very-long-execution-lines-tiny-change.patch @@ -0,0 +1,56 @@ +From 61b5e58f18f152636a77c872dc39281bfb8bf90d Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Fri, 17 Jan 2020 20:49:33 +0100 +Subject: [PATCH] sed: handle very long execution lines (tiny change) + +If sed is called with an excessively long execution line, then it is +prone to an out of bounds memory access. + +The problem is that the length of the execution line, which is a +size_t, is temporarily stored in an int. This means that on systems +which have a 64 bit size_t and a 32 bit int (e.g. linux amd64) an +execution line which exceeds 2 GB will overflow int. If it is just +slightly larger than 2 GB, the negative int value is used as an +array index to finish the execution line string with '\0' which +therefore triggers the out of bounds access. + +This problem is probably never triggered in reality, but can be +provoked like this (given that 'e' support is compiled in): + +$ dd if=/dev/zero bs=1M count=2049 | tr '\0' e > e-command.txt +$ sed -f e-command.txt /etc/fstab +Segmentation fault (core dumped) + +Also adjust another int/size_t conversion, even though it is a +purely cosmetic change, because it can never be larger than 4096. + +* sed/execute.c (execute_program) [case 'e']: Declare cmd_length +to be of type size_t, not int. Likewise for "n" just below. +* NEWS (Bug fixes): Mention it. +This addresses https://bugs.gnu.org/39165 +--- + sed/execute.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sed/execute.c b/sed/execute.c +index c5f07cc..8f43f2e 100644 +--- a/sed/execute.c ++++ b/sed/execute.c +@@ -1347,7 +1347,7 @@ execute_program (struct vector *vec, struct input *input) + panic (_("`e' command not supported")); + #else + FILE *pipe_fp; +- int cmd_length = cur_cmd->x.cmd_txt.text_length; ++ size_t cmd_length = cur_cmd->x.cmd_txt.text_length; + line_reset (&s_accum, NULL); + + if (!cmd_length) +@@ -1367,7 +1367,7 @@ execute_program (struct vector *vec, struct input *input) + + { + char buf[4096]; +- int n; ++ size_t n; + while (!feof (pipe_fp)) + if ((n = fread (buf, sizeof (char), 4096, pipe_fp)) > 0) + { diff --git a/backport-sed-handle-very-long-input-lines-with-R-tiny-change.patch b/backport-sed-handle-very-long-input-lines-with-R-tiny-change.patch new file mode 100644 index 0000000..12d5bbc --- /dev/null +++ b/backport-sed-handle-very-long-input-lines-with-R-tiny-change.patch @@ -0,0 +1,55 @@ +From acabfdb582330345c05e0500d302e9e99f3eb5e9 Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Fri, 17 Jan 2020 21:28:28 +0100 +Subject: [PATCH] sed: handle very long input lines with R (tiny change) + +It is possible to trigger an out of bounds memory access when +using the sed command R with an input file containing very long +lines. + +The problem is that the line length of parsed file is returned as +a size_t by ck_getdelim, but temporarily stored in an int and +then converted back into a size_t. On systems like amd64, on which +this problem can be triggered, size_t and int have different sizes. + +If the input line is longer than 2 GB (which is parseable on amd64 +or other 64 bit systems), this means that the temporarily stored +int turns negative. Converting the negative int back into a size_t +will lead to an excessively large size_t, as the conversion leads to +a lot of leading 1 bits. + +Eventually ck_fwrite is called with this huge size_t which in turn +will lead to an out of bounds access on amd64 systems -- after all +the parsed text was just a bit above 2 GB, not near SIZE_MAX. + +You can trigger this issue with GNU sed on OpenBSD like this: + +$ dd if=/dev/zero bs=1M count=2049 | tr '\0' e > long.txt +$ sed Rlong.txt /etc/fstab +Segmentation fault (core dumped) + +I was unable to trigger the bug on a Linux system with glibc due to +a bug in glibc's fwrite implementation -- it leads to a short write +and sed treats that correctly as an error. + +* sed/execute.c (execute_program) [case 'R']: Declare result +to be of type size_t, not int. +* NEWS (Bug fixes): Mention it. +This addresses https://bugs.gnu.org/39166 +--- + sed/execute.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletion(-) + +diff --git a/sed/execute.c b/sed/execute.c +index 8f43f2e..f94b125 100644 +--- a/sed/execute.c ++++ b/sed/execute.c +@@ -1518,7 +1518,7 @@ execute_program (struct vector *vec, struct input *input) + struct append_queue *aq; + size_t buflen; + char *text = NULL; +- int result; ++ size_t result; + + result = ck_getdelim (&text, &buflen, buffer_delimiter, + cur_cmd->x.inf->fp); diff --git a/sed.spec b/sed.spec index 142374b..4736056 100644 --- a/sed.spec +++ b/sed.spec @@ -1,12 +1,16 @@ Name: sed Version: 4.8 -Release: 1 +Release: 2 Summary: non-interactive command-line text editor License: GPLv3+ URL: https://www.gnu.org/software/sed/ Source0: http://ftp.gnu.org/gnu/sed/%{name}-%{version}.tar.xz +Patch1: backport-sed-c-flag.patch +Patch2: backport-sed-handle-very-long-execution-lines-tiny-change.patch +Patch3: backport-sed-handle-very-long-input-lines-with-R-tiny-change.patch + BuildRequires: gzip automake autoconf gcc BuildRequires: glibc-devel libselinux-devel libacl-devel perl-Getopt-Long Provides: /bin/sed @@ -47,6 +51,12 @@ make %{?_smp_mflags} %{_mandir}/man1/*.1.gz %changelog +* Tue Feb 8 2021 yangzhuangzhuang - 4.8-2 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:backport patches from upstream + * Thu Apr 16 2020 chengquan - 4.8-1 - Type:enhancement - ID:NA -- Gitee