Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzz: Panic: 'path should be resolved'. #174

Closed
kuzminrobin opened this issue Apr 18, 2023 · 5 comments
Closed

Fuzz: Panic: 'path should be resolved'. #174

kuzminrobin opened this issue Apr 18, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@kuzminrobin
Copy link
Contributor

kuzminrobin commented Apr 18, 2023

(Fuzzer found)
The input file with contents namespace N{operation P(a:i):D{}} causes a panic
thread 'main' panicked at 'path should be resolved', compiler\qsc_frontend\src\typeck\rules.rs:126:22

Looks like the reason is the parameter type. If the type is anything other than Int or Double or Qubit (or array of them) then there is a panic.

Repro:

echo namespace N{operation P(a:i):D{}}> t.qs

@rem Both
qsc.exe t.qs
@rem and
qsc.exe - < t.qs
@rem Result in panic.

However! Related or not, the comment affects the panic:

@rem Add an empty comment in front of the fragment that causes panic:
echo //>t3.qs
echo namespace N{operation P(a:i):D{}}>> t3.qs

@rem See the file content:
type t3.qs 

//
namespace N{operation P(a:i):D{}}

qsc.exe t3.qs
@rem Panic

qsc.exe - < t3.qs
@rem No panic. Compilation error instead:
  × entry point not found
  help: a single callable with the `@EntryPoint()` attribute must be present if no entry expression is provided

Stack:

Stack trace for "t.qs" in fuzzer run (click the triangle on the left):
   0: rust_begin_unwind
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/std/src/panicking.rs:577:5
   1: core::panicking::panic_fmt
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/panicking.rs:67:14
   2: core::panicking::panic_display
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/panicking.rs:150:5
   3: core::panicking::panic_str
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/panicking.rs:134:5
   4: core::option::expect_failed
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/option.rs:2025:5
   5: core::option::Option<T>::expect
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/option.rs:913:21
   6: qsc_frontend::typeck::rules::Context::infer_ty
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/rules.rs:126:22
   7: qsc_frontend::typeck::rules::Context::infer_pat
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/rules.rs:524:26
   8: qsc_frontend::typeck::rules::Context::infer_pat
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/rules.rs:530:38
   9: qsc_frontend::typeck::rules::Context::infer_spec
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/rules.rs:87:30
  10: qsc_frontend::typeck::rules::spec
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/rules.rs:603:5
  11: qsc_frontend::typeck::check::Checker::check_spec
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/check.rs:93:22
  12: <qsc_frontend::typeck::check::Checker as qsc_ast::visit::Visitor>::visit_callable_decl
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/check.rs:120:43
  13: qsc_ast::visit::walk_item
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_ast/src/visit.rs:91:37
  14: qsc_ast::visit::Visitor::visit_item
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_ast/src/visit.rs:20:9
  15: qsc_ast::visit::walk_namespace::{{closure}}
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_ast/src/visit.rs:84:41
  16: <core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::for_each
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/core/src/slice/iter/macros.rs:201:21
  17: qsc_ast::visit::walk_namespace
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_ast/src/visit.rs:84:5
  18: qsc_ast::visit::Visitor::visit_namespace
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_ast/src/visit.rs:16:9
  19: <qsc_frontend::typeck::check::Checker as qsc_ast::visit::Visitor>::visit_package
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/typeck/check.rs:106:13
  20: qsc_frontend::compile::typeck_all
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/compile.rs:305:5
  21: qsc_frontend::compile::compile
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_frontend/src/compile.rs:176:28
  22: qsc_eval::stateless::create_execution_context
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_eval/src/stateless.rs:172:16
  23: qsc_eval::stateless::compile_execution_context
             at /mnt/c/ed/dev/QSharpCompiler/qsharp-runtime/qsharp/compiler/qsc_eval/src/stateless.rs:109:5
  24: qsc_wasm::run_internal
             at ./src/lib.rs:307:19
  25: run_internal::_::__libfuzzer_sys_run
             at ./fuzz/fuzz_targets/run_internal.rs:10:17
  26: rust_fuzzer_test_input
             at /home/rokuzmin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/src/lib.rs:224:17
  27: libfuzzer_sys::test_input_wrap::{{closure}}
             at /home/rokuzmin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/src/lib.rs:61:9
  28: std::panicking::try::do_call
             at /rustc/88fb1b922b047981fc0cfc62aa1418b4361ae72e/library/std/src/panicking.rs:485:40
  29: __rust_try
  (Further frames are fuzzer's. Available if needed)

System information

  • OS: Fuzzer found in WSL. The repro steps are run in Win.
  • Commit (in branch "kuzminrobin/fuzz"):
commit 5092ecf88e609120761f1aa1c488a33fefbbd0f7 (HEAD -> kuzminrobin/fuzz)
Author: Robin Kuzmin <kuzmin.robin@gmail.com>
Date:   Mon Apr 17 16:26:03 2023 -0700
    Renamed some corpus files.
  • Based on commit in main:
commit d6de27819fe20989abfce6a2bad74d9e6b366caf (origin/main, origin/HEAD, main)
Author: Sarah Marshall <33814365+samarsha@users.noreply.github.com>
Date:   Wed Apr 12 12:45:51 2023 -0700
    Parse empty statements (#147)
@kuzminrobin kuzminrobin added the bug Something isn't working label Apr 18, 2023
@bamarsha
Copy link
Contributor

I can reproduce with d6de278, but not latest main. I think #163 accidentally fixed this, because it changed the type checker to no longer try to resolve paths in types. Let me know if updating helps.

@kuzminrobin
Copy link
Contributor Author

Confirmed, the panic is resolved. I'm unblocked.


But the Q# code comment still changes the behavior between the commands qsc.exe t3.qs and qsc.exe - < t3.qs. I'm not sure if this is something that requires fixing or not, if yes then whether the current GitHub item needs to be reopened or a new one created. Up to you.
It is at least interesting to know why the comment affects the behavior, may be there is some hidden bug...

qsc.exe t3.qs

  × `i` not found in this scope
   ╭─[t3.qs:1:1]
 1 │ //
 2 │ namespace N{operation P(a:i):D{}}
   ·                           ┬
   ·                           ╰── not found
   ╰────


  × `D` not found in this scope
   ╭─[t3.qs:1:1]
 1 │ //
 2 │ namespace N{operation P(a:i):D{}}
   ·                              ┬
   ·                              ╰── not found
   ╰────


  × mismatched types
   ╭─[t3.qs:1:1]
 1 │ //
 2 │ namespace N{operation P(a:i):D{}}
   ·                               ─┬
   ·                                ╰── expected ?, found ()
   ╰────

qsc.exe - < t3.qs

  × entry point not found
  help: a single callable with the `@EntryPoint()` attribute must be present if no entry expression is provided

Also the following bug reporting seems misleading to me:

 2 │ namespace N{operation P(a:i):D{}}
   ·                               ─┬
   ·                                ╰── expected ?, found ()

Complains that found () whereas there is {} in the input stream.


Also the following fragment seems misleading to me in all the cases [t3.qs:1:1]. Refers to a wrong line and column.

@bamarsha
Copy link
Contributor

But the Q# code comment still changes the behavior between the commands qsc.exe t3.qs and qsc.exe - < t3.qs. I'm not sure if this is something that requires fixing or not, if yes then whether the current GitHub item needs to be reopened or a new one created. Up to you.
It is at least interesting to know why the comment affects the behavior, may be there is some hidden bug...

I think this is a separate bug with how qsc is reading stdin. It looks like the newline after the comment is getting eaten, because that error happens with an empty input file. Can you file another issue?

Also the following bug reporting seems misleading to me:

 2 │ namespace N{operation P(a:i):D{}}
   ·                               ─┬
   ·                                ╰── expected ?, found ()

Complains that found () whereas there is {} in the input stream.

The error is correct, although possibly confusing. The type of {} (empty block) is () (empty tuple).

Also the following fragment seems misleading to me in all the cases [t3.qs:1:1]. Refers to a wrong line and column.

This is how Miette renders errors. It shows the position of the start of the excerpt. Since the excerpt shows the entire file, it starts at line 1, column 1.

@kuzminrobin
Copy link
Contributor Author

Can you file another issue?

#188

The error is correct, although possibly confusing. The type of {} (empty block) is () (empty tuple).

FYI: This is really confusing that the function/operation body (or a block starting with { and ending with } and containing that body) has a data type (separate from the function/operation signature type). It makes an impression that one can declare/define a variable of that type. Is that really possible? If not then why do we need a data type for the function/operation body (or a block containing body)?

@bamarsha
Copy link
Contributor

bamarsha commented Apr 20, 2023

I think the confusion comes from the fact that blocks are expressions. The type of the body block is equal to the return type of the function or operation. The return value of a function or operation is the value that comes from evaluating the body block as an expression. For example:

function AddOne(x : Int) : Int {
    let y = x + 1;
    y
}

When you call AddOne(2), x is bound to 2, and then the expression { let y = x + 1; y } is evaluated. So, yeah, the block has type Int. It just happens that an empty block evaluates to the unit tuple by default, so it has type () (also written as Unit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants