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

Crash when calling print on the return of an empty UDF #595

Closed
MarcusParadies opened this issue Aug 30, 2023 · 2 comments · Fixed by #605
Closed

Crash when calling print on the return of an empty UDF #595

MarcusParadies opened this issue Aug 30, 2023 · 2 comments · Fixed by #605
Labels
bug A mistake in the code.

Comments

@MarcusParadies
Copy link
Contributor

MarcusParadies commented Aug 30, 2023

Daphne (v0.2 && main branch) crashes when invoking print() on an empty UDF (not return types, no statements in body).

DSL script:

def f() {}
print(f());

Stacktrace:

(gdb) bt  
#0  0x000055ef013749bd in mlir::Type::isSignedInteger(unsigned int) const ()
#1  0x000055ef007abcb1 in mlir::daphne::__mlir_ods_local_type_constraint_DaphneOps37 (op=0x55ef0626b190, type=..., valueKind=..., valueIndex=0)
    at /home/marcus/code/daphne_fork/build/src/ir/daphneir/DaphneOps.cpp.inc:605
#2  0x000055ef0083e5cb in mlir::daphne::PrintOp::verifyInvariantsImpl (this=0x7f3c3c0cb550) at /home/marcus/code/daphne_fork/build/src/ir/daphneir/DaphneOps.cpp.inc:22591
#3  0x000055ef00a5704b in mlir::OpTrait::OpInvariants<mlir::daphne::PrintOp>::verifyTrait (op=0x55ef0626b190)
    at /home/marcus/code/daphne_fork/thirdparty/installed/include/mlir/IR/OpDefinition.h:371
#4  0x000055ef00a2b52e in mlir::op_definition_impl::verifyTrait<mlir::OpTrait::OpInvariants<mlir::daphne::PrintOp> > (op=0x55ef0626b190)
    at /home/marcus/code/daphne_fork/thirdparty/installed/include/mlir/IR/OpDefinition.h:1565
#5  0x000055ef009f18c0 in mlir::op_definition_impl::verifyTraits<mlir::OpTrait::ZeroRegions<mlir::daphne::PrintOp>, mlir::OpTrait::ZeroResults<mlir::daphne::PrintOp>, mlir::OpTrait::ZeroSuccessors<mlir::daphne::PrintOp>, mlir::OpTrait::NOperands<3u>::Impl<mlir::daphne::PrintOp>, mlir::OpTrait::OpInvariants<mlir::daphne::PrintOp> > (op=0x55ef0626b190)
    at /home/marcus/code/daphne_fork/thirdparty/installed/include/mlir/IR/OpDefinition.h:1576
#6  0x000055ef009cd957 in mlir::Op<mlir::daphne::PrintOp, mlir::OpTrait::ZeroRegions, mlir::OpTrait::ZeroResults, mlir::OpTrait::ZeroSuccessors, mlir::OpTrait::NOperands<3u>::Impl, mlir::OpTrait::OpInvariants>::verifyInvariants (op=0x55ef0626b190) at /home/marcus/code/daphne_fork/thirdparty/installed/include/mlir/IR/OpDefinition.h:1861
#7  0x000055ef00a1ff29 in llvm::detail::UniqueFunctionBase<mlir::LogicalResult, mlir::Operation*>::CallImpl<mlir::LogicalResult (* const)(mlir::Operation*)> (CallableAddr=0x7f3c3c0cb660,
    Params#0=0x55ef0626b190) at /home/marcus/code/daphne_fork/thirdparty/installed/include/llvm/ADT/FunctionExtras.h:221
#8  0x000055ef009b3293 in llvm::unique_function<mlir::LogicalResult (mlir::Operation*) const>::operator()(mlir::Operation*) const (this=0x7f3c3c0cb660, Params#0=0x55ef0626b190)
    at /home/marcus/code/daphne_fork/thirdparty/installed/include/llvm/ADT/FunctionExtras.h:409
#9  0x000055ef0098e4b5 in mlir::RegisteredOperationName::Model<mlir::daphne::PrintOp>::verifyInvariants (this=0x55ef06221650, op=0x55ef0626b190)
    at /home/marcus/code/daphne_fork/thirdparty/installed/include/mlir/IR/OperationSupport.h:411
#10 0x000055ef013770d9 in (anonymous namespace)::OperationVerifier::verifyOperation(mlir::Operation&) ()
#11 0x000055ef013773cb in (anonymous namespace)::OperationVerifier::verifyOperation(mlir::Operation&) ()
#12 0x000055ef01378ef6 in std::_Function_handler<void (), mlir::failableParallelForEach<mlir::Operation**, (anonymous namespace)::OperationVerifier::verifyOperation(mlir::Operation&)::$_0>(mlir::MLIRContext*, mlir::Operation**, mlir::Operation**, (anonymous namespace)::OperationVerifier::verifyOperation(mlir::Operation&)::$_0&&)::{lambda()#1}>::_M_invoke(std::_Any_data const&)
    ()
#13 0x000055ef01056bd2 in std::_Function_handler<void (), llvm::ThreadPool::createTaskAndFuture(std::function<void ()>)::{lambda()#1}>::_M_invoke(std::_Any_data const&) ()
#14 0x000055ef035f2274 in llvm::ThreadPool::processTasks(llvm::ThreadPoolTaskGroup*) ()
#15 0x000055ef035f2ef3 in void* llvm::thread::ThreadProxy<std::tuple<llvm::ThreadPool::grow(int)::$_0> >(void*) ()
#16 0x00007f3c3d494b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#17 0x00007f3c3d526a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

I'm assuming that since no return type is known/can be deduced there is a segfault when checking for the type. Imho the daphne compiler should not accept such a script since no return type can be deduced from the function. Options to handle this could be either to enforce the user to have at least one return statement within a UDF or fail the compilation of no return type can be deduced from the UDF.

@corepointer
Copy link
Collaborator

In my debugger it shows that it actually crashes the DAPHNE compiler. So we should maybe catch that already while parsing? 🤔

@corepointer corepointer added the bug A mistake in the code. label Aug 30, 2023
@corepointer
Copy link
Collaborator

After investigating this further, I found out, that the reason for the crash is an invalid mlir::Value that is returned when a function does not have a return value. I have a local fix for this that returns nullptr instead of that invalid mlir::Value and then later checking on that nullptr to ignore that return value.
Furthermore I'd throw an error for empty function bodies (I added a check before inserting the ReturnOp). I'll push that tomorrow for review 😪

corepointer added a commit to corepointer/daphne that referenced this issue Sep 7, 2023
…unction

This commit contains two changes more or less related to this issue:

1. There is a check preventing empty function definitions. While I thought the empty function had something to do with the crash at first, this turned out to be not the case. Nevertheless, I kept the change as reminding the user that there's unnecessary code would improve our compiler a tiny little bit (imho).

2. The core issue seems to be that functions without return value internally returned an invalid mlir::Value. Upon doing anything with this value, the program would crash (e.g. accessing any fields or calling any methods). Now we return nullptr and check for that, which gives a somewhat more deterministic behavior.

Closes daphne-eu#595
corepointer added a commit to corepointer/daphne that referenced this issue Jun 28, 2024
…unction

The core issue seems to be that functions without return value internally returned an invalid mlir::Value. Upon doing anything with this value, the program would crash (e.g. accessing any fields or calling any methods). Now we return nullptr and check for that, which gives a somewhat more deterministic behavior.

Closes daphne-eu#595
corepointer added a commit to corepointer/daphne that referenced this issue Jul 5, 2024
…unction

The core issue seems to be that functions without return value internally returned an invalid mlir::Value. Upon doing anything with this value, the program would crash (e.g. accessing any fields or calling any methods). Now we return nullptr and check for that, which gives a somewhat more deterministic behavior.

Closes daphne-eu#595
pdamme added a commit to corepointer/daphne that referenced this issue Jul 11, 2024
- So far, the code in this PR checked, for each argument to a function call, if it is nullptr ("result" of a UDF without return values), and if so, ignored the argument.
  - This is not correct, since:
    - 1) We cannot simply ignore erroneous arguments. For instance, when function foo() has no return values, then "print(foo());" should fail and "print(foo(), 0);" should not print "0", but also fail.
    - 2) Call arguments are just one out of many places where a UDF with zero results could be used in DaphneDSL. All these places should be handled consistently. In fact, we have valueOrError() for that purpose and it already covers this case.
  - So this change was undone.
  - Note that the error message displayed to the user is not informative yet, but that will be improved in a follow-up commit.
- Added several script-level test cases.
  - Check that DAPHNE does not accept UDFs with zero or more than one return value in places where exactly one value is expected.
  - All of these tests on a UDF with zero return values crash DAPHNE with a segfault on main (so problem in daphne-eu#595) is not specific to call expressions).
  - These are just a few examples, actually we should have test cases for all uses of "expr" in the DaphneDSL grammar.
@pdamme pdamme closed this as completed in 3e56ed5 Jul 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A mistake in the code.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants