Projects
Factory:RISC-V:Base
emacs
_service:tar_scm:backport-CVE-2022-45939.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-CVE-2022-45939.patch of Package emacs
From d48bb4874bc6cd3e69c7a15fc3c91cc141025c51 Mon Sep 17 00:00:00 2001 From: lu4nx <lx@shellcodes.org> Date: Fri, 25 Nov 2022 14:38:29 +0800 Subject: Fixed ctags local command execute vulnerability * lib-src/etags.c: (clean_matched_file_tag): New function (do_move_file): New function (readline_internal): Add `leave_cr` parameter, if true, include the \r character * test/manual/etags/CTAGS.good_crlf: New file * test/manual/etags/CTAGS.good_update: New file * test/manual/etags/crlf: New file * test/manual/etags/Makefile: Add `ctags -u` test cases Conflict:Removed test case related code, so the patch is over 9000 lines, it's too big Reference:https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=d48bb4874bc6cd3e69c7a15fc3c91cc141025c51 --- lib-src/etags.c | 149 +- 1 files changed, 113 insertions(+), 36 deletions(-) diff --git a/lib-src/etags.c b/lib-src/etags.c index 3107c7b..b6f51df 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -375,7 +375,7 @@ static void just_read_file (FILE *); static language *get_language_from_langname (const char *); static void readline (linebuffer *, FILE *); -static ptrdiff_t readline_internal (linebuffer *, FILE *, char const *); +static ptrdiff_t readline_internal (linebuffer *, FILE *, char const *, const bool); static bool nocase_tail (const char *); static void get_tag (char *, char **); static void get_lispy_tag (char *); @@ -399,7 +399,9 @@ static void free_fdesc (fdesc *); static void pfnote (char *, bool, char *, ptrdiff_t, intmax_t, intmax_t); static void invalidate_nodes (fdesc *, node **); static void put_entries (node *); +static void clean_matched_file_tag (char const * const, char const * const); +static void do_move_file (const char *, const char *); static char *concat (const char *, const char *, const char *); static char *skip_spaces (char *); static char *skip_non_spaces (char *); @@ -1332,7 +1334,7 @@ main (int argc, char **argv) if (parsing_stdin) fatal ("cannot parse standard input " "AND read file names from it"); - while (readline_internal (&filename_lb, stdin, "-") > 0) + while (readline_internal (&filename_lb, stdin, "-", false) > 0) process_file_name (filename_lb.buffer, lang); } else @@ -1380,9 +1382,6 @@ main (int argc, char **argv) /* From here on, we are in (CTAGS && !cxref_style) */ if (update) { - char *cmd = - xmalloc (strlen (tagfile) + whatlen_max + - sizeof "mv..OTAGS;grep -Fv '\t\t' OTAGS >;rm OTAGS"); for (i = 0; i < current_arg; ++i) { switch (argbuffer[i].arg_type) @@ -1393,17 +1392,8 @@ main (int argc, char **argv) default: continue; /* the for loop */ } - char *z = stpcpy (cmd, "mv "); - z = stpcpy (z, tagfile); - z = stpcpy (z, " OTAGS;grep -Fv '\t"); - z = stpcpy (z, argbuffer[i].what); - z = stpcpy (z, "\t' OTAGS >"); - z = stpcpy (z, tagfile); - strcpy (z, ";rm OTAGS"); - if (system (cmd) != EXIT_SUCCESS) - fatal ("failed to execute shell command"); + clean_matched_file_tag (tagfile, argbuffer[i].what); } - free (cmd); append_to_tagfile = true; } @@ -1448,6 +1438,51 @@ main (int argc, char **argv) return EXIT_SUCCESS; } +/* + * Equivalent to: mv tags OTAGS;grep -Fv ' filename ' OTAGS >tags;rm OTAGS + */ +static void +clean_matched_file_tag (const char* tagfile, const char* match_file_name) +{ + FILE *otags_f = fopen ("OTAGS", "wb"); + FILE *tag_f = fopen (tagfile, "rb"); + + if (otags_f == NULL) + pfatal ("OTAGS"); + + if (tag_f == NULL) + pfatal (tagfile); + + int buf_len = strlen (match_file_name) + sizeof ("\t\t ") + 1; + char *buf = xmalloc (buf_len); + snprintf (buf, buf_len, "\t%s\t", match_file_name); + + linebuffer line; + linebuffer_init (&line); + while (readline_internal (&line, tag_f, tagfile, true) > 0) + { + if (ferror (tag_f)) + pfatal (tagfile); + + if (strstr (line.buffer, buf) == NULL) + { + fprintf (otags_f, "%s\n", line.buffer); + if (ferror (tag_f)) + pfatal (tagfile); + } + } + free (buf); + free (line.buffer); + + if (fclose (otags_f) == EOF) + pfatal ("OTAGS"); + + if (fclose (tag_f) == EOF) + pfatal (tagfile); + + do_move_file ("OTAGS", tagfile); + return; +} /* * Return a compressor given the file name. If EXTPTR is non-zero, @@ -1831,7 +1866,7 @@ find_entries (FILE *inf) /* Else look for sharp-bang as the first two characters. */ if (parser == NULL - && readline_internal (&lb, inf, infilename) > 0 + && readline_internal (&lb, inf, infilename, false) > 0 && lb.len >= 2 && lb.buffer[0] == '#' && lb.buffer[1] == '!') @@ -6878,7 +6913,7 @@ analyze_regex (char *regex_arg) if (regexfp == NULL) pfatal (regexfile); linebuffer_init (®exbuf); - while (readline_internal (®exbuf, regexfp, regexfile) > 0) + while (readline_internal (®exbuf, regexfp, regexfile, false) > 0) analyze_regex (regexbuf.buffer); free (regexbuf.buffer); if (fclose (regexfp) != 0) @@ -7226,11 +7261,13 @@ get_lispy_tag (register char *bp) /* * Read a line of text from `stream' into `lbp', excluding the - * newline or CR-NL, if any. Return the number of characters read from - * `stream', which is the length of the line including the newline. + * newline or CR-NL (if `leave_cr` is false), if any. Return the + * number of characters read from `stream', which is the length + * of the line including the newline. * - * On DOS or Windows we do not count the CR character, if any before the - * NL, in the returned length; this mirrors the behavior of Emacs on those + * On DOS or Windows, if `leave_cr` is false, we do not count the + * CR character, if any before the NL, in the returned length; + * this mirrors the behavior of Emacs on those * platforms (for text files, it translates CR-NL to NL as it reads in the * file). * @@ -7238,7 +7275,7 @@ get_lispy_tag (register char *bp) * appended to `filebuf'. */ static ptrdiff_t -readline_internal (linebuffer *lbp, FILE *stream, char const *filename) +readline_internal (linebuffer *lbp, FILE *stream, char const *filename, const bool leave_cr) { char *buffer = lbp->buffer; char *p = lbp->buffer; @@ -7268,19 +7305,19 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename) break; } if (c == '\n') - { - if (p > buffer && p[-1] == '\r') - { - p -= 1; - chars_deleted = 2; - } - else - { - chars_deleted = 1; - } - *p = '\0'; - break; - } + { + if (!leave_cr && p > buffer && p[-1] == '\r') + { + p -= 1; + chars_deleted = 2; + } + else + { + chars_deleted = 1; + } + *p = '\0'; + break; + } *p++ = c; } lbp->len = p - buffer; @@ -7311,7 +7348,7 @@ static void readline (linebuffer *lbp, FILE *stream) { linecharno = charno; /* update global char number of line start */ - ptrdiff_t result = readline_internal (lbp, stream, infilename); + ptrdiff_t result = readline_internal (lbp, stream, infilename, false); lineno += 1; /* increment global line number */ charno += result; /* increment global char number */ @@ -7669,6 +7706,46 @@ etags_mktmp (void) return templt; } +static void +do_move_file(const char *src_file, const char *dst_file) +{ + if (rename (src_file, dst_file) == 0) + return; + + FILE *src_f = fopen (src_file, "rb"); + FILE *dst_f = fopen (dst_file, "wb"); + + if (src_f == NULL) + pfatal (src_file); + + if (dst_f == NULL) + pfatal (dst_file); + + int c; + while ((c = fgetc (src_f)) != EOF) + { + if (ferror (src_f)) + pfatal (src_file); + + if (ferror (dst_f)) + pfatal (dst_file); + + if (fputc (c, dst_f) == EOF) + pfatal ("cannot write"); + } + + if (fclose (src_f) == EOF) + pfatal (src_file); + + if (fclose (dst_f) == EOF) + pfatal (dst_file); + + if (unlink (src_file) == -1) + pfatal ("unlink error"); + + return; +} + /* Return a newly allocated string containing the file name of FILE relative to the absolute directory DIR (which should end with a slash). */ static char * -- cgit v1.1
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2