From 250733c0d86d392c6e37b62cc82df0c396362581 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 11 Jul 2023 10:46:36 +0900 Subject: [PATCH] common: Add gnupg_check_special_filename. * common/sysutils.h (gnupg_check_special_filename): New. * common/sysutils.c (gnupg_check_special_filename): New. * common/iobuf.c (translate_file_handle): Remove. (iobuf_is_pipe_filename): Use gnupg_check_special_filename. (do_open): Use gnupg_check_special_filename. * g10/plaintext.c (get_output_file): Use gnupg_check_special_filename and open_stream_nc. -- GnuPG-bug-id: 6580 Signed-off-by: NIIBE Yutaka --- common/iobuf.c | 40 ++++------------------------------------ common/sysutils.c | 42 ++++++++++++++++++++++++++++++++++++++++++ common/sysutils.h | 1 + g10/plaintext.c | 10 +++++----- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/common/iobuf.c b/common/iobuf.c index 477a66874..2427e4f19 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -166,7 +166,6 @@ block_filter_ctx_t; /* Local prototypes. */ static int underflow (iobuf_t a, int clear_pending_eof); static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target); -static gnupg_fd_t translate_file_handle (int fd, int for_write); static iobuf_t do_iobuf_fdopen (gnupg_fd_t fp, const char *mode, int keep_open); @@ -1412,7 +1411,7 @@ iobuf_is_pipe_filename (const char *fname) { if (!fname || (*fname=='-' && !fname[1]) ) return 1; - return check_special_filename (fname, 0, 1) != -1; + return gnupg_check_special_filename (fname) != GNUPG_INVALID_FD; } @@ -1425,7 +1424,7 @@ do_open (const char *fname, int special_filenames, file_filter_ctx_t *fcx; size_t len = 0; int print_only = 0; - int fd; + gnupg_fd_t fd; byte desc[MAX_IOBUF_DESC]; log_assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT); @@ -1449,9 +1448,8 @@ do_open (const char *fname, int special_filenames, else if (!fname) return NULL; else if (special_filenames - && (fd = check_special_filename (fname, 0, 1)) != -1) - return do_iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT - ? 0 : 1), opentype, 0); + && (fd = gnupg_check_special_filename (fname)) != GNUPG_INVALID_FD) + return do_iobuf_fdopen (fd, opentype, 0); else { if (use == IOBUF_INPUT) @@ -2948,36 +2946,6 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, return nbytes; } -static gnupg_fd_t -translate_file_handle (int fd, int for_write) -{ -#if defined(HAVE_W32_SYSTEM) - { - gnupg_fd_t x; - - (void)for_write; - - if (fd == 0) - x = GetStdHandle (STD_INPUT_HANDLE); - else if (fd == 1) - x = GetStdHandle (STD_OUTPUT_HANDLE); - else if (fd == 2) - x = GetStdHandle (STD_ERROR_HANDLE); - else - x = (gnupg_fd_t)(intptr_t)fd; - - if (x == INVALID_HANDLE_VALUE) - log_debug ("GetStdHandle(%d) failed: ec=%d\n", - fd, (int) GetLastError ()); - - return x; - } -#else - (void)for_write; - return fd; -#endif -} - void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial) diff --git a/common/sysutils.c b/common/sysutils.c index 745b762ba..80aa3a04a 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -682,6 +682,48 @@ check_special_filename (const char *fname, int for_write, int notranslate) } +/* Check whether FNAME has the form "-&nnnn", where N is a number + * representing a file. Returns GNUPG_INVALID_FD if it is not the + * case. Returns a file descriptor on POSIX, a system handle on + * Windows. */ +gnupg_fd_t +gnupg_check_special_filename (const char *fname) +{ + if (allow_special_filenames + && fname && *fname == '-' && fname[1] == '&') + { + int i; + + fname += 2; + for (i=0; digitp (fname+i); i++ ) + ; + if (!fname[i]) + { + es_syshd_t syshd; + + if (gnupg_parse_fdstr (fname, &syshd)) + return GNUPG_INVALID_FD; + +#ifdef HAVE_W32_SYSTEM + if (syshd.type == ES_SYSHD_FD) + { + if (syshd.u.fd == 0) + return GetStdHandle (STD_INPUT_HANDLE); + else if (syshd.u.fd == 1) + return GetStdHandle (STD_OUTPUT_HANDLE); + else if (syshd.u.fd == 2) + return GetStdHandle (STD_ERROR_HANDLE); + } + else + return syshd.u.handle; +#else + return syshd.u.fd; +#endif + } + } + return GNUPG_INVALID_FD; +} + /* Replacement for tmpfile(). This is required because the tmpfile function of Windows' runtime library is broken, insecure, ignores TMPDIR and so on. In addition we create a file with an inheritable diff --git a/common/sysutils.h b/common/sysutils.h index 8cc303b61..c6740a874 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -76,6 +76,7 @@ int translate_sys2libc_fd (gnupg_fd_t fd, int for_write); int translate_sys2libc_fd_int (int fd, int for_write); gpg_error_t gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd); int check_special_filename (const char *fname, int for_write, int notranslate); +gnupg_fd_t gnupg_check_special_filename (const char *fname); FILE *gnupg_tmpfile (void); void gnupg_reopen_std (const char *pgmname); void gnupg_inhibit_set_foregound_window (int yes); diff --git a/g10/plaintext.c b/g10/plaintext.c index 3d54b843c..9544ddf03 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -111,20 +111,20 @@ get_output_file (const byte *embedded_name, int embedded_namelen, { /* Special file name, no filename, or "-" given; write to the * file descriptor or to stdout. */ - int fd; + gnupg_fd_t fd; char xname[64]; - fd = check_special_filename (fname, 1, 0); - if (fd == -1) + fd = gnupg_check_special_filename (fname); + if (fd == GNUPG_INVALID_FD) { /* Not a special filename, thus we want stdout. */ fp = es_stdout; es_set_binary (fp); } - else if (!(fp = es_fdopen_nc (fd, "wb"))) + else if (!(fp = open_stream_nc (fd, "wb"))) { err = gpg_error_from_syserror (); - snprintf (xname, sizeof xname, "[fd %d]", fd); + snprintf (xname, sizeof xname, "[fd %d]", (int)(intptr_t)fd); log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err)); goto leave; }