summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-03-09 20:30:06 -0800
committerKaz Kylheku <kaz@kylheku.com>2017-03-09 20:30:06 -0800
commit0ceb62ad1eddfdc0ade20005829c845afec67d81 (patch)
tree268f8b7e90dc4afa4bae6474e4df8446a29fd8d0
parent4d0cdf070aa173c6e4ca23ff05e00a5f1731efa5 (diff)
downloadtxr-0ceb62ad1eddfdc0ade20005829c845afec67d81.tar.gz
txr-0ceb62ad1eddfdc0ade20005829c845afec67d81.tar.bz2
txr-0ceb62ad1eddfdc0ade20005829c845afec67d81.zip
Don't open streams or stdin on non-matching directives.
* match.c (open_data_source): The logic of not opening the data source for a non-matching directive must be applied to streams also, because the lazy list mechanism will read ahead from an underlying non-interactive stream. We must also apply it in the case when we open standard input by default. If standard input is non-interactive such that the lazy list unconditionally tries to read a line from it upon construction, we misbehave. The program could block on the read. Even if it doesn't block, the input action is an unwanted externally visible event.
-rw-r--r--match.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/match.c b/match.c
index cda3c28c..63cd572a 100644
--- a/match.c
+++ b/match.c
@@ -4382,6 +4382,10 @@ static val h_assert(match_line_ctx *c)
static void open_data_source(match_files_ctx *c)
{
spec_bind (specline, first_spec, c->spec);
+ int non_matching_dir = (consp(first_spec) &&
+ (gethash(non_matching_directive_table,
+ first(first_spec))) &&
+ !rest(specline));
/* c->data == t is set up by the top level call to match_files.
* It indicates that we have not yet opened any data source.
@@ -4393,32 +4397,27 @@ static void open_data_source(match_files_ctx *c)
val name = ss_consp ? cdr(source_spec) : source_spec;
val nothrow = tnil(ss_consp && car(source_spec) == nothrow_k);
- if (stringp(name)) {
- if (consp(first_spec) &&
- (gethash(non_matching_directive_table, first(first_spec))) &&
- !rest(specline))
- {
- debuglf(first_spec, lit("not opening source ~a "
- "since query starts with non-matching "
- "directive."), name, nao);
- } else {
- val stream = complex_open(name, nil, nil, nothrow, t);
+ if (non_matching_dir) {
+ debuglf(first_spec, lit("not opening source ~a "
+ "since query starts with non-matching "
+ "directive."), name, nao);
+ } else if (stringp(name)) {
+ val stream = complex_open(name, nil, nil, nothrow, t);
- debuglf(specline, lit("opening data source ~a"), name, nao);
+ debuglf(specline, lit("opening data source ~a"), name, nao);
- if (!stream) {
- debuglf(first_spec, lit("could not open ~a: "
- "treating as failed match due to nothrow"), name, nao);
- c->data = nil;
- return;
- }
+ if (!stream) {
+ debuglf(first_spec, lit("could not open ~a: "
+ "treating as failed match due to nothrow"), name, nao);
+ c->data = nil;
+ return;
+ }
- c->files = cons(name, cdr(c->files)); /* Get rid of cons and nothrow */
- c->curfile = source_spec;
+ c->files = cons(name, cdr(c->files)); /* Get rid of cons and nothrow */
+ c->curfile = source_spec;
- if ((c->data = lazy_stream_cons(stream)) != nil)
- c->data_lineno = one;
- }
+ if ((c->data = lazy_stream_cons(stream)) != nil)
+ c->data_lineno = one;
} else if (streamp(name)) {
if ((c->data = lazy_stream_cons(name)))
c->data_lineno = one;
@@ -4428,6 +4427,10 @@ static void open_data_source(match_files_ctx *c)
} else if (c->data == t && c->files == nil) {
if (opt_compat && opt_compat <= 170) {
c->data = nil;
+ } else if (non_matching_dir) {
+ debuglf(first_spec, lit("not opening standard input "
+ "since query starts with non-matching "
+ "directive."), nao);
} else {
debuglf(first_spec, lit("opening standard input as data source"), nao);
c->curfile = lit("-");