bug#28417: ptx does not terminate when matching a zero length sentence regex

2017-09-11 Thread Julian Büning
observed behavior:

$ echo | ptx -S $ &
[1] 1000
$ jobs
[1]+  Running echo | ptx -S $ &

expected behavior:

$ echo | ptx -S $ &
[1] 1000
[1]+  Doneecho | ptx -S $

ptx does not terminate in case the specified sentence regex can be
matched but has a match of length zero on input that is non-empty.

The following test cases show the same behavior:
$ echo | ptx -S ^
$ echo | ptx -S "a*"
$ echo | ptx -S "\(\)"
$ echo test | ptx -S "\n*"
$ echo foo > non_empty; ptx non_empty -S $
...

In ptx.c, find_occurs_in_text() calls re_search() and uses the length of
a match (which is falsely assumed to be greater than zero) to advance a
cursor through the input. For a match length of zero, the cursor is
never advanced.

When switching on the results of re_search(), a case 0 could be added.
One possible fix would be to then abort with an error message.

We found this behavior in version 8.27 and can reproduce it in version
8.25 as well as version 8.28.

This behavior was found using Symbolic Execution techniques developed in
the course of the SYMBIOSYS research project at COMSYS, RWTH Aachen
University. This research is supported by the European Research Council
(ERC) under the EU's Horizon 2020 Research and Innovation Programme
grant agreement n. 647295 (SYMBIOSYS).

Best regards,
Julian





bug#24903: "tail -f - foo" does not terminate when stdin is closed and foo is ignored

2016-11-18 Thread Julian Büning

On 11/08/2016 06:47 PM, Pádraig Brady wrote:

p.s. These Symbolic Execution techniques are intriguing.
Have you any more details.


Thanks for your interest in our techniques. Symbolic Execution is a 
dynamic analysis method to automatically find bugs by executing a 
program with symbolic inputs, therefore reasoning about all possible 
execution paths. We based our work on KLEE [1], a symbolic execution 
engine, which has previously been used to find memory access violations 
in the GNU Coreutils suite [2]. We extended KLEE by adding the ability 
to automatically find unintended non-termination, such as the two bugs 
we reported on this mailing list. Unfortunately, I cannot share any 
details right now, as we are currently preparing a publication of our 
work. I will be happy to follow up once our paper has been published.


[1] http://klee.github.io
[2] http://llvm.org/pubs/2008-12-OSDI-KLEE.html

Regards,
Julian





bug#24903: "tail -f - foo" does not terminate when stdin is closed and foo is ignored

2016-11-08 Thread Julian Büning

We observed another behavior possibly related to bug #24495:

$ mkdir foo
$ echo "bar" | tail -f - foo &
[1] 16386
==> standard input <==
bar

==> foo <==
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
$ jobs
[1]+  Running echo "bar" | tail -f - foo &
$ readlink /proc/16386/fd/0
pipe:[162156]
$ lsof | grep 162156
tail  16386  user0r FIFO   0,10   0t0
162156 pipe

Only the reading end of the pipe is still open, thus tail should not be
able to read any more bytes from it.


expected behavior:

$ mkdir foo
$ echo "bar" | tail -f - foo &
[1] 16386
==> standard input <==
bar

==> foo <==
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
tail: no files remaining
[1]+  Doneecho "bar" | tail -f - foo &

This would match the behavior of tail when called without a directory as
parameter:

$ echo "bar" | tail -f - &
[1] 8411
bar
[1]+  Doneecho "bar" | tail -f -


We could reproduce this behavior with version 8.25 (package) and
8.25.91-23066 (compiled from source) on Fedora.

We need the directory (or some other untailable file) as second argument 
to reproduce this behavior as the -f option is ignored for any FIFO or 
pipe using ignore_fifo_and_pipe(), which prevents tail_forever() from 
being called in case only FIFOs or pipes are available. The 
aforementioned function sets .ignore to true for any FIFO or pipe.


In our test case, tail_forever() skips both the directory and stdin as
their .ignore entries are set to true. Before sleeping and starting the
next iteration of the loop (without making any attempt to read from
stdin), any_live_files() is called, which returns true for stdin:
 > if (0 <= f[i].fd)
 >return true;


This behavior was found using Symbolic Execution techniques developed in
the course of the SYMBIOSYS research project at COMSYS, RWTH Aachen
University.

Regards,
Julian Büning





bug#24495: tail -F does not terminate when running out of names to watch

2016-09-21 Thread Julian Büning

observed behavior:

$ mkdir foo
$ tail -F foo &
[1] 1000
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
$ rmdir foo ; echo moo > foo
$ jobs
[1]+  Running tail -F foo &

expected behavior option 1:

$ mkdir foo
$ tail -F foo &
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
$ rmdir foo ; echo moo > foo
[1]+  Done tail -F foo &

expected behavior option 2:

$ mkdir foo
$ tail -F foo &
[1] 1000
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file
$ rmdir foo ; echo moo > foo
tail: 'foo' has appeared;  following new file
moo
$ jobs
[1]+  Running tail -F foo &

tail does neither terminate nor display any contents of the file foo.
We would assume that either tail terminates after displaying the error
message (because there is no other file left) or that tail would
infinitely retry to read a file with the same name and if such a file
is created.

We could reproduce this behavior with versions 8.25 on ArchLinux and
8.25 and 8.25.71-1db94 on Fedora (package and compiled from source)
with and without ---disable-inotify. At least in version 8.25,
tail_forever_inotify is not executed because any_non_remote_file
returns false, which disables inotify in line 2361 (tail.c).

We can trace the cause of this behavior for the non-inotify version of
tail_forever:
For a directory, the ignore flag in the corresponding struct File_spec
is set to true. Thus, tail_forever skips this file in line 1130 (tail.c)
and does not modify this flag during any iteration of the enclosing
while(1). Since no check is being done if any valid target remains,
this leads to the observed non-terminating behavior.

This behavior was found using Symbolic Execution techniques developed in
the course of the SYMBIOSYS research project at COMSYS, RWTH Aachen
University.

Regards,
Julian Büning