diff options
author | Thomas Weißschuh <thomas@t-8ch.de> | 2024-04-13 10:34:32 +0200 |
---|---|---|
committer | Thomas Weißschuh <thomas@t-8ch.de> | 2024-04-13 13:04:36 +0200 |
commit | 12707a4948c1bcd54859824b26a46f530f0949d0 (patch) | |
tree | 93444d8c9edc9d803b77da6e6e1b8e8982e71480 | |
parent | ccb3af024cb134acb391a44283dec4ed40c3605b (diff) | |
download | util-linux-12707a4948c1bcd54859824b26a46f530f0949d0.tar.gz |
textutils: introduce and use fgetwc_or_err
A return value of WEOF of fgetwc() can either mean end-of-file or an
error in errno. The error was ignored and interpreted as end-of-file.
Introduce a new helper that aborts on error and use it in text-utils.
This replaces all calls to plain fgetwc().
Closes #2909
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
-rw-r--r-- | include/Makemodule.am | 1 | ||||
-rw-r--r-- | include/fgetwc_or_err.h | 23 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-crash1 | 3 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-crash1.err | 1 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-crash2 | 2 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-crash2.err | 1 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-hang1 | 2 | ||||
-rw-r--r-- | tests/expected/colcrt/regressions-hang1.err | 1 | ||||
-rwxr-xr-x | tests/ts/colcrt/regressions | 1 | ||||
-rw-r--r-- | text-utils/colcrt.c | 7 | ||||
-rw-r--r-- | text-utils/colrm.c | 7 | ||||
-rw-r--r-- | text-utils/rev.c | 3 | ||||
-rw-r--r-- | text-utils/ul.c | 7 |
13 files changed, 45 insertions, 14 deletions
diff --git a/include/Makemodule.am b/include/Makemodule.am index 50a8546128..bdf87e2213 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -26,6 +26,7 @@ dist_noinst_HEADERS += \ include/env.h \ include/exec_shell.h \ include/exitcodes.h \ + include/fgetwc_or_err.h \ include/fileeq.h \ include/fileutils.h \ include/fuzz.h \ diff --git a/include/fgetwc_or_err.h b/include/fgetwc_or_err.h new file mode 100644 index 0000000000..3cf9262834 --- /dev/null +++ b/include/fgetwc_or_err.h @@ -0,0 +1,23 @@ +#ifndef UTIL_LINUX_FGETWC_OR_ERR_H +#define UTIL_LINUX_FGETWC_OR_ERR_H + +#include <stdio.h> +#include <wchar.h> +#include <errno.h> + +#include "widechar.h" +#include "c.h" +#include "nls.h" + +static inline wint_t fgetwc_or_err(FILE *stream) { + wint_t ret; + + errno = 0; + ret = fgetwc(stream); + if (ret == WEOF && errno != 0) + err(EXIT_FAILURE, _("fgetwc() failed")); + + return ret; +} + +#endif /* _FGETWC_OR_ERR_H */ diff --git a/tests/expected/colcrt/regressions-crash1 b/tests/expected/colcrt/regressions-crash1 index 67a7b1c998..3b41a79524 100644 --- a/tests/expected/colcrt/regressions-crash1 +++ b/tests/expected/colcrt/regressions-crash1 @@ -1,2 +1 @@ - W U; U; D f U; D f D f > @W ]~ K- - ---- -- -- - -- -- ---- -- ---- -- - -- --- -- -return value: 0 +return value: 1 diff --git a/tests/expected/colcrt/regressions-crash1.err b/tests/expected/colcrt/regressions-crash1.err new file mode 100644 index 0000000000..5837df340c --- /dev/null +++ b/tests/expected/colcrt/regressions-crash1.err @@ -0,0 +1 @@ +colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character diff --git a/tests/expected/colcrt/regressions-crash2 b/tests/expected/colcrt/regressions-crash2 index 11ebf74a8f..58a43173eb 100644 --- a/tests/expected/colcrt/regressions-crash2 +++ b/tests/expected/colcrt/regressions-crash2 @@ -7,4 +7,4 @@ MN MN9| XYZ nT RnTUV| NXP:w - -MNOP.return value: 0 +return value: 1 diff --git a/tests/expected/colcrt/regressions-crash2.err b/tests/expected/colcrt/regressions-crash2.err new file mode 100644 index 0000000000..5837df340c --- /dev/null +++ b/tests/expected/colcrt/regressions-crash2.err @@ -0,0 +1 @@ +colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character diff --git a/tests/expected/colcrt/regressions-hang1 b/tests/expected/colcrt/regressions-hang1 index cb16e46a34..78fb568e5b 100644 --- a/tests/expected/colcrt/regressions-hang1 +++ b/tests/expected/colcrt/regressions-hang1 @@ -1,3 +1,3 @@ 789:;<=>=>?IABUVNXYZ[ `abcdefgg !"#$%&'()*+,-./01234)*:,-./0123456789:;[=>?1234)*:,-./0123456789:;[=>?4456789:;<=>?IABUVN`abcdefg !" - -return value: 0 +return value: 1 diff --git a/tests/expected/colcrt/regressions-hang1.err b/tests/expected/colcrt/regressions-hang1.err new file mode 100644 index 0000000000..5837df340c --- /dev/null +++ b/tests/expected/colcrt/regressions-hang1.err @@ -0,0 +1 @@ +colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character diff --git a/tests/ts/colcrt/regressions b/tests/ts/colcrt/regressions index 7bbba658be..2bb846959a 100755 --- a/tests/ts/colcrt/regressions +++ b/tests/ts/colcrt/regressions @@ -28,6 +28,7 @@ check_input_file() { ts_init_subtest ${1##*/} timeout 2 env LC_ALL=C.UTF-8 $TS_CMD_COLCRT < $1 >> $TS_OUTPUT 2>> $TS_ERRLOG echo "return value: $?" >> $TS_OUTPUT + sed -i -e 's/Illegal byte sequence/Invalid or incomplete multibyte or wide character/' $TS_ERRLOG ts_finalize_subtest } diff --git a/text-utils/colcrt.c b/text-utils/colcrt.c index 44d2c8a8c8..4a1214cc80 100644 --- a/text-utils/colcrt.c +++ b/text-utils/colcrt.c @@ -49,6 +49,7 @@ #include "c.h" #include "widechar.h" #include "closestream.h" +#include "fgetwc_or_err.h" /* * colcrt - replaces col for crts with new nroff esp. when using tbl. @@ -164,7 +165,7 @@ static void colcrt(struct colcrt_control *ctl) errno = 0; old_pos = ftell(ctl->f); - while (fgetwc(ctl->f) != L'\n') { + while (fgetwc_or_err(ctl->f) != L'\n') { long new_pos; if (ferror(ctl->f) || feof(ctl->f)) @@ -179,10 +180,10 @@ static void colcrt(struct colcrt_control *ctl) col = -1; continue; } - c = fgetwc(ctl->f); + c = fgetwc_or_err(ctl->f); switch (c) { case 033: /* ESC */ - c = fgetwc(ctl->f); + c = fgetwc_or_err(ctl->f); if (c == L'8') { col = rubchars(ctl, col, 1); continue; diff --git a/text-utils/colrm.c b/text-utils/colrm.c index d893137164..363d732b62 100644 --- a/text-utils/colrm.c +++ b/text-utils/colrm.c @@ -48,6 +48,7 @@ #include "c.h" #include "widechar.h" #include "closestream.h" +#include "fgetwc_or_err.h" /* COLRM removes unwanted columns from a file @@ -81,7 +82,7 @@ static int process_input(unsigned long first, unsigned long last) int padding; for (;;) { - c = fgetwc(stdin); + c = fgetwc_or_err(stdin); if (c == WEOF) return 0; if (c == '\t') @@ -112,7 +113,7 @@ static int process_input(unsigned long first, unsigned long last) /* Loop getting rid of characters */ while (!last || ct < last) { - c = fgetwc(stdin); + c = fgetwc_or_err(stdin); if (c == WEOF) return 0; if (c == '\n') { @@ -135,7 +136,7 @@ static int process_input(unsigned long first, unsigned long last) /* Output last of the line */ for (;;) { - c = fgetwc(stdin); + c = fgetwc_or_err(stdin); if (c == WEOF) break; if (c == '\n') { diff --git a/text-utils/rev.c b/text-utils/rev.c index 4b731890d8..fc7ac6203b 100644 --- a/text-utils/rev.c +++ b/text-utils/rev.c @@ -63,6 +63,7 @@ #include "widechar.h" #include "c.h" #include "closestream.h" +#include "fgetwc_or_err.h" static void sig_handler(int signo __attribute__ ((__unused__))) { @@ -100,7 +101,7 @@ static size_t read_line(wchar_t sep, wchar_t *str, size_t n, FILE *stream) { size_t r = 0; while (r < n) { - wint_t c = fgetwc(stream); + wint_t c = fgetwc_or_err(stream); if (c == WEOF) break; str[r++] = c; diff --git a/text-utils/ul.c b/text-utils/ul.c index 1df4642eb3..62bfcd7bf9 100644 --- a/text-utils/ul.c +++ b/text-utils/ul.c @@ -62,6 +62,7 @@ #include "widechar.h" #include "c.h" #include "closestream.h" +#include "fgetwc_or_err.h" #define ESC '\033' #define SO '\016' @@ -439,7 +440,7 @@ static int handle_escape(struct ul_ctl *ctl, struct term_caps const *const tcs, { wint_t c; - switch (c = fgetwc(f)) { + switch (c = fgetwc_or_err(f)) { case HREV: if (0 < ctl->half_position) { ctl->mode &= ~SUBSCRIPT; @@ -479,7 +480,7 @@ static void filter(struct ul_ctl *ctl, struct term_caps const *const tcs, FILE * wint_t c; int i, width; - while ((c = fgetwc(f)) != WEOF) { + while ((c = fgetwc_or_err(f)) != WEOF) { switch (c) { case '\b': set_column(ctl, ctl->column && 0 < ctl->column ? ctl->column - 1 : 0); @@ -498,7 +499,7 @@ static void filter(struct ul_ctl *ctl, struct term_caps const *const tcs, FILE * continue; case ESC: if (handle_escape(ctl, tcs, f)) { - c = fgetwc(f); + c = fgetwc_or_err(f); errx(EXIT_FAILURE, _("unknown escape sequence in input: %o, %o"), ESC, c); } |