aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Weißschuh <thomas@t-8ch.de>2024-04-13 10:34:32 +0200
committerThomas Weißschuh <thomas@t-8ch.de>2024-04-13 13:04:36 +0200
commit12707a4948c1bcd54859824b26a46f530f0949d0 (patch)
tree93444d8c9edc9d803b77da6e6e1b8e8982e71480
parentccb3af024cb134acb391a44283dec4ed40c3605b (diff)
downloadutil-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.am1
-rw-r--r--include/fgetwc_or_err.h23
-rw-r--r--tests/expected/colcrt/regressions-crash13
-rw-r--r--tests/expected/colcrt/regressions-crash1.err1
-rw-r--r--tests/expected/colcrt/regressions-crash22
-rw-r--r--tests/expected/colcrt/regressions-crash2.err1
-rw-r--r--tests/expected/colcrt/regressions-hang12
-rw-r--r--tests/expected/colcrt/regressions-hang1.err1
-rwxr-xr-xtests/ts/colcrt/regressions1
-rw-r--r--text-utils/colcrt.c7
-rw-r--r--text-utils/colrm.c7
-rw-r--r--text-utils/rev.c3
-rw-r--r--text-utils/ul.c7
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);
}