summaryrefslogtreecommitdiffstats
path: root/match.c
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 /match.c
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.
Diffstat (limited to 'match.c')
-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("-");