]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
textutils: introduce and use fgetwc_or_err
authorThomas Weißschuh <thomas@t-8ch.de>
Sat, 13 Apr 2024 08:34:32 +0000 (10:34 +0200)
committerThomas Weißschuh <thomas@t-8ch.de>
Sat, 13 Apr 2024 11:04:36 +0000 (13:04 +0200)
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>
13 files changed:
include/Makemodule.am
include/fgetwc_or_err.h [new file with mode: 0644]
tests/expected/colcrt/regressions-crash1
tests/expected/colcrt/regressions-crash1.err [new file with mode: 0644]
tests/expected/colcrt/regressions-crash2
tests/expected/colcrt/regressions-crash2.err [new file with mode: 0644]
tests/expected/colcrt/regressions-hang1
tests/expected/colcrt/regressions-hang1.err [new file with mode: 0644]
tests/ts/colcrt/regressions
text-utils/colcrt.c
text-utils/colrm.c
text-utils/rev.c
text-utils/ul.c

index 50a8546128edd44e6e13e5ac4d2f4215dc37b902..bdf87e2213bf91e77c12df0c4bfe73d10fcad289 100644 (file)
@@ -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 (file)
index 0000000..3cf9262
--- /dev/null
@@ -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 */
index 67a7b1c998c9f9ddeb0b8f297701404ad15c8e4d..3b41a7952446f017bd7e48f8e5c0e8930f20fd58 100644 (file)
@@ -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 (file)
index 0000000..5837df3
--- /dev/null
@@ -0,0 +1 @@
+colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character
index 11ebf74a8fd0493bccbdbd64eb8390a2a382261a..58a43173eb7a276180b8102e4f3da2f3792e9bb9 100644 (file)
@@ -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 (file)
index 0000000..5837df3
--- /dev/null
@@ -0,0 +1 @@
+colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character
index cb16e46a347a9950c05e90f84d581c5e8d277b04..78fb568e5b107bf9352ee38af11f7348fe14605e 100644 (file)
@@ -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 (file)
index 0000000..5837df3
--- /dev/null
@@ -0,0 +1 @@
+colcrt: fgetwc() failed: Invalid or incomplete multibyte or wide character
index 7bbba658be1747e68ee1010e89b29e6f8e610e35..2bb846959af53d4e004f2b507cb8872827b6d2cc 100755 (executable)
@@ -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
 }
 
index 44d2c8a8c8c1994ed149379e0e80f69a57e68c0f..4a1214cc8068e0841e9c2ed83184c6da1cb2e392 100644 (file)
@@ -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;
index d893137164f0f6b14ab0e8f3184b763f47419ed1..363d732b6201297b16a5f119630dd82b244753ea 100644 (file)
@@ -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') {
index 4b731890d8da732fd32e4bd348ec28b132327099..fc7ac6203bd3796341e86e3b6307a546a59a1b83 100644 (file)
@@ -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;
index 1df4642eb38bd64524c603d7804c88d911afdc9c..62bfcd7bf9c8f04dbec4935081bfd6e2fa6163ee 100644 (file)
@@ -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);
                        }