From 5f58e1cfd7ecbc7d2825a4640bbceaf609303cd4 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sat, 13 Sep 2025 14:37:53 +0200 Subject: [PATCH 1/8] reproduce panick originating in set_input/1 call from top-level Signed-off-by: Thierry Marianne --- .../issues/set_input_from_input_file_stream.in/input | 1 + .../set_input_from_top-level.pl | 10 ++++++++++ .../cli/issues/set_input_from_input_file_stream.stderr | 0 .../cli/issues/set_input_from_input_file_stream.stdin | 0 .../cli/issues/set_input_from_input_file_stream.stdout | 1 + .../cli/issues/set_input_from_input_file_stream.toml | 1 + 6 files changed, 13 insertions(+) create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.in/input create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.in/set_input_from_top-level.pl create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.stderr create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.stdin create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.stdout create mode 100644 tests/scryer/cli/issues/set_input_from_input_file_stream.toml diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.in/input b/tests/scryer/cli/issues/set_input_from_input_file_stream.in/input new file mode 100644 index 00000000..60c0d887 --- /dev/null +++ b/tests/scryer/cli/issues/set_input_from_input_file_stream.in/input @@ -0,0 +1 @@ +true. \ No newline at end of file diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.in/set_input_from_top-level.pl b/tests/scryer/cli/issues/set_input_from_input_file_stream.in/set_input_from_top-level.pl new file mode 100644 index 00000000..b38f2223 --- /dev/null +++ b/tests/scryer/cli/issues/set_input_from_input_file_stream.in/set_input_from_top-level.pl @@ -0,0 +1,10 @@ +:- use_module(library(files)). + +main :- + current_input(UserStream), + open('./input', read, InputStream), + set_input(InputStream), + read_term(T, []), write(T), + set_input(UserStream). + +:- initialization(main). diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.stderr b/tests/scryer/cli/issues/set_input_from_input_file_stream.stderr new file mode 100644 index 00000000..e69de29b diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.stdin b/tests/scryer/cli/issues/set_input_from_input_file_stream.stdin new file mode 100644 index 00000000..e69de29b diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.stdout b/tests/scryer/cli/issues/set_input_from_input_file_stream.stdout new file mode 100644 index 00000000..f32a5804 --- /dev/null +++ b/tests/scryer/cli/issues/set_input_from_input_file_stream.stdout @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/tests/scryer/cli/issues/set_input_from_input_file_stream.toml b/tests/scryer/cli/issues/set_input_from_input_file_stream.toml new file mode 100644 index 00000000..e488fd1f --- /dev/null +++ b/tests/scryer/cli/issues/set_input_from_input_file_stream.toml @@ -0,0 +1 @@ +args = ["-f", "--no-add-history", "-g", "consult('set_input_from_top-level.pl').", "-g", "halt."] From 5c341ce3712d2b5a38b36ef59b90ff0a06b2df73 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sun, 14 Sep 2025 12:00:55 +0200 Subject: [PATCH 2/8] handle input file stream on term reading from user input --- src/machine/machine_state.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 148a9d8f..d40d564d 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -755,6 +755,14 @@ impl MachineState { ); } + if let Stream::InputFile(_) = stream { + return self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ); + } + if let Stream::Byte(_) = stream { return self.read_term( stream, From fdbaf6ac9d6c324bc8d5cf47c6ec8a7a7cae17dd Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sun, 14 Sep 2025 13:47:26 +0200 Subject: [PATCH 3/8] handle named tcp and http read stream on term reading from user input --- src/machine/machine_state.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index d40d564d..237fafbb 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -755,6 +755,15 @@ impl MachineState { ); } + #[cfg(feature = "http")] + if let Stream::HttpRead(_) = stream { + return self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ); + } + if let Stream::InputFile(_) = stream { return self.read_term( stream, @@ -763,6 +772,14 @@ impl MachineState { ); } + if let Stream::NamedTcp(_) = stream { + return self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ); + } + if let Stream::Byte(_) = stream { return self.read_term( stream, From be18eda696a3f6205f0b5d15f1f8121f0ea32bc5 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sun, 14 Sep 2025 16:42:12 +0200 Subject: [PATCH 4/8] do not reset user input `Stream` of kind different from `Readline(_)`, `Byte(_)` Signed-off-by: Thierry Marianne --- src/machine/system_calls.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 5eb9a6d2..01f2b2ec 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -6739,7 +6739,10 @@ impl Machine { #[inline(always)] pub(crate) fn read_query_term(&mut self) -> CallResult { - self.user_input.reset(); + match self.user_input { + Stream::Byte(_) | Stream::Readline(_) => self.user_input.reset(), + _ => true, + }; set_prompt(true); // let result = self.machine_st.read_term(self.user_input, &mut self.indices); @@ -6751,7 +6754,10 @@ impl Machine { match result { Ok(()) => Ok(()), Err(e) => { - self.user_input.reset(); + match self.user_input { + Stream::Byte(_) | Stream::Readline(_) => self.user_input.reset(), + _ => true + }; Err(e) } } From 1ece558a71e2a8b8a15beb5e8f72b452d9cbe740 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sun, 14 Sep 2025 17:00:39 +0200 Subject: [PATCH 5/8] match against `Stream` `HttpRead()`, `InputFile(_)` and `NamedTcp(_)` variants in read_term_from_user_input Signed-off-by: Thierry Marianne --- src/machine/machine_state.rs | 42 ++++++++++++++++-------------------- src/machine/system_calls.rs | 2 +- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 237fafbb..e1124222 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -755,30 +755,24 @@ impl MachineState { ); } - #[cfg(feature = "http")] - if let Stream::HttpRead(_) = stream { - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ); - } - - if let Stream::InputFile(_) = stream { - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ); - } - - if let Stream::NamedTcp(_) = stream { - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ); - } + match stream { + #[cfg(feature = "http")] + Stream::HttpRead(_) => { + return self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ) + } + Stream::InputFile(_) | Stream::NamedTcp(_) => { + return self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ) + } + _ => true, + }; if let Stream::Byte(_) = stream { return self.read_term( diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 01f2b2ec..baad0153 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -6756,7 +6756,7 @@ impl Machine { Err(e) => { match self.user_input { Stream::Byte(_) | Stream::Readline(_) => self.user_input.reset(), - _ => true + _ => true, }; Err(e) } From 28ec45715978add714a8790abb8b6f23f2909c11 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Sun, 14 Sep 2025 18:32:30 +0200 Subject: [PATCH 6/8] merge if let, match structures Signed-off-by: Thierry Marianne --- src/machine/machine_state.rs | 49 +++++++++++++----------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index e1124222..a3c141e0 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -745,44 +745,29 @@ impl MachineState { stream: Stream, indices: &mut IndexStore, ) -> CallResult { - if let Stream::Readline(ptr) = stream { - let readline = unsafe { ptr.as_ptr().as_mut() }.unwrap(); - readline.set_atoms_for_completion(&self.atom_tbl); - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ); - } - match stream { #[cfg(feature = "http")] - Stream::HttpRead(_) => { - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ) - } - Stream::InputFile(_) | Stream::NamedTcp(_) => { - return self.read_term( - stream, - indices, - MachineState::read_term_from_user_input_eof_handler, - ) - } - _ => true, - }; - - if let Stream::Byte(_) = stream { - return self.read_term( + Stream::HttpRead(_) => self.read_term( stream, indices, MachineState::read_term_from_user_input_eof_handler, - ); + ), + Stream::Readline(ptr) => { + let readline = unsafe { ptr.as_ptr().as_mut() }.unwrap(); + readline.set_atoms_for_completion(&self.atom_tbl); + self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ) + } + Stream::Byte(_) | Stream::InputFile(_) | Stream::NamedTcp(_) => self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ), + _ => Err(functor_stub(atom!("read_term_from_user_input"), 3)), } - - unreachable!("Stream must be a Stream::Readline(_)") } pub fn read_term_eof_handler(&mut self, mut stream: Stream) -> Result { From e9834ffa3ea8680479205bc0dbfaa4de092075fe Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Mon, 15 Sep 2025 08:28:23 +0200 Subject: [PATCH 7/8] throw permission_error when non-input stream is read Signed-off-by: Thierry Marianne --- src/machine/machine_state.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index a3c141e0..26ba9a69 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -766,7 +766,16 @@ impl MachineState { indices, MachineState::read_term_from_user_input_eof_handler, ), - _ => Err(functor_stub(atom!("read_term_from_user_input"), 3)), + _ => { + let stub = functor_stub(atom!("read_term_from_user_input"), 3); + let err = self.permission_error( + Permission::InputStream, + atom!("stream"), + atom_as_cell!(atom!("user_input")), + ); + + Err(self.error_form(err, stub)) + } } } From 8afcc7742b2d8b1c2166adbf9721836d8738b252 Mon Sep 17 00:00:00 2001 From: Thierry Marianne Date: Mon, 15 Sep 2025 08:33:47 +0200 Subject: [PATCH 8/8] handle `Stream` variants qualified as input stream by `is_input_stream` Signed-off-by: Thierry Marianne --- src/machine/machine_state.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 26ba9a69..ca88a6ea 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -752,6 +752,12 @@ impl MachineState { indices, MachineState::read_term_from_user_input_eof_handler, ), + #[cfg(feature = "tls")] + Stream::NamedTls(_) => self.read_term( + stream, + indices, + MachineState::read_term_from_user_input_eof_handler, + ), Stream::Readline(ptr) => { let readline = unsafe { ptr.as_ptr().as_mut() }.unwrap(); readline.set_atoms_for_completion(&self.atom_tbl); @@ -761,7 +767,13 @@ impl MachineState { MachineState::read_term_from_user_input_eof_handler, ) } - Stream::Byte(_) | Stream::InputFile(_) | Stream::NamedTcp(_) => self.read_term( + Stream::Byte(_) + | Stream::InputChannel(_) + | Stream::InputFile(_) + | Stream::NamedTcp(_) + | Stream::Null(_) + | Stream::PipeReader(_) + | Stream::StaticString(_) => self.read_term( stream, indices, MachineState::read_term_from_user_input_eof_handler,