]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
more: improve zero size handling
authorTobias Stoeckmann <tobias@stoeckmann.org>
Sun, 16 Jan 2022 21:14:23 +0000 (22:14 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Sun, 16 Jan 2022 21:14:23 +0000 (22:14 +0100)
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 <tobias@stoeckmann.org>
text-utils/more.c

index f1f6d38f78d8ceacb44ad9436e08c4917244c30e..a0d62bd5bf33c661f1f89f7c06fc2c0dc69c80eb 100644 (file)
@@ -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