From 8fd1e76631343aa2f0dadf8dcc511889e54e14f9 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Sun, 16 Jan 2022 22:14:23 +0100 Subject: [PATCH] more: improve zero size handling Sami Kerola pointed out that /proc contains files with zero size but content in ec4153cc28c718e064a1992a76a63ec7696d33a6. Eventually fixes for better type handling have been committed with ba105bb5eb0052ee7d85d0903ad4ae9e87114930 and error handling when "more" is called with directories in 32a4efc5675ca238d382a0027f7f4723b8b3af28. This commit fixes a regression and wrong file size handling: checkf ends execution prematurely if st.st_size is 0. The idea was to skip the check_magic call which would otherwise claim that a text file would not be one, e.g. /proc/self/wchan would fail otherwise. This has two consequences: 1. The last check in checkf is never true, because if st_size is 0 we already left the function (file_size and st_size are both off_t). Proof of Concept (use a window with less lines than /proc/cpuinfo): $ echo "hello world" > /tmp/more-poc $ more /tmp/more-poc /proc/cpuinfo - Press space to switch to next file - You see >100% in status line 2. Leaving early does not set the close on exit flag for empty files. 3. Since the last line is never reached, ~(off_t)0 is never set, which implies that the check in display_file is never true. The st.st_size = 0 case is supposed to be special. Simplify this regression fix by considering ctl->file_size = 0 to be special. This eleminates the ~(off_t)0 magic, which would be -1. Signed-off-by: Tobias Stoeckmann --- text-utils/more.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/text-utils/more.c b/text-utils/more.c index f1f6d38f78..a0d62bd5bf 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -450,6 +450,7 @@ static void checkf(struct more_control *ctl, char *fs) ctl->current_line = 0; ctl->file_position = 0; + ctl->file_size = 0; fflush(NULL); ctl->current_file = fopen(fs, "r"); @@ -468,10 +469,8 @@ static void checkf(struct more_control *ctl, char *fs) ctl->current_file = NULL; return; } - if (st.st_size == 0) { - return; - } - if (check_magic(ctl, fs)) { + ctl->file_size = st.st_size; + if (0 < ctl->file_size && check_magic(ctl, fs)) { fclose(ctl->current_file); ctl->current_file = NULL; return; @@ -480,8 +479,6 @@ static void checkf(struct more_control *ctl, char *fs) c = more_getc(ctl); ctl->clear_first = (c == '\f'); more_ungetc(ctl, c); - if ((ctl->file_size = st.st_size) == 0) - ctl->file_size = ~((off_t)0); } static void prepare_line_buffer(struct more_control *ctl) @@ -1912,7 +1909,7 @@ static void display_file(struct more_control *ctl, int left) more_key_command(ctl, ctl->file_names[ctl->argv_position]); if (left != 0) { if ((ctl->no_scroll || ctl->clear_first) - && ctl->file_size != ~((off_t)0)) { + && 0 < ctl->file_size) { if (ctl->clear_line_ends) putp(ctl->go_home); else -- 2.39.5