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

DuckDB SIGSEGV when doing ill-formed date type casting #10140

Closed
1 task done
SteveLeungYL opened this issue Jan 4, 2024 · 3 comments · Fixed by #10142
Closed
1 task done

DuckDB SIGSEGV when doing ill-formed date type casting #10140

SteveLeungYL opened this issue Jan 4, 2024 · 3 comments · Fixed by #10142

Comments

@SteveLeungYL
Copy link

What happens?

In the latest main version of DuckDB (version 6b4f65a) and the released version v0.9.2 (3c695d7), the applications crash when executing the following query sequence:

SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL SECONDS [ ] [ ] :: SETOF NCHAR ARRAY :: FLOAT ; 

Here is a crash stack trace from version 6b4f65a:

#0  0x0000555555fd3261 in duckdb::ListCast::ListToListCast (source=..., result=..., count=count@entry=0x0, parameters=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/function/cast/list_casts.cpp:45
#1  0x0000555555fd3330 in duckdb::ListToVarcharCast (source=..., result=..., count=0x0, parameters=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/function/cast/list_casts.cpp:74
#2  0x0000555555fd31f5 in duckdb::ListCast::ListToListCast (source=..., result=..., count=<optimized out>, parameters=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/function/cast/list_casts.cpp:64
#3  0x0000555555a6b875 in duckdb::ExpressionExecutor::Execute (this=this@entry=0x7fffffffa3f0, expr=..., state=state@entry=0x5555572ab070, sel=sel@entry=0x0,
    count=count@entry=0x1, result=...) at /home/luy70/Desktop/DBMSs/duckdb/src/execution/expression_executor/execute_cast.cpp:39
#4  0x0000555555bc463f in duckdb::ExpressionExecutor::Execute (this=this@entry=0x7fffffffa3f0, expr=..., state=0x5555572ab070, sel=sel@entry=0x0, count=count@entry=0x1,
    result=...) at /home/luy70/Desktop/DBMSs/duckdb/src/execution/expression_executor.cpp:200
#5  0x0000555555a6b7ca in duckdb::ExpressionExecutor::Execute (this=this@entry=0x7fffffffa3f0, expr=..., state=state@entry=0x5555572aaf80, sel=sel@entry=0x0,
    count=count@entry=0x1, result=...) at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/common/unique_ptr.hpp:19
#6  0x0000555555bc463f in duckdb::ExpressionExecutor::Execute (this=0x7fffffffa3f0, expr=..., state=0x5555572aaf80, sel=0x0, count=0x1, result=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/execution/expression_executor.cpp:200
#7  0x0000555555bc483d in duckdb::ExpressionExecutor::ExecuteExpression (this=0x7fffffffa3f0, expr_idx=0x0, result=...) at /usr/include/c++/9/bits/stl_vector.h:1040
#8  0x0000555555bc4e50 in duckdb::ExpressionExecutor::EvaluateScalar (context=..., expr=..., allow_unfoldable=<optimized out>)
    at /home/luy70/Desktop/DBMSs/duckdb/src/execution/expression_executor.cpp:116
#9  0x0000555555bc4ef1 in duckdb::ExpressionExecutor::TryEvaluateScalar (context=..., expr=..., result=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/execution/expression_executor.cpp:126
#10 0x000055555586a676 in duckdb::FunctionBinder::BindScalarFunction (this=this@entry=0x7fffffffa908, func=..., children=..., error="", is_operator=<optimized out>,
    binder=0x55555719ecc0) at /usr/include/c++/9/bits/unique_ptr.h:360
#11 0x0000555555df48a2 in duckdb::ExpressionBinder::BindFunction (this=0x7fffffffb730, function=..., func=..., depth=<optimized out>)
    at /usr/include/c++/9/bits/stl_vector.h:99
#12 0x0000555555df9b42 in duckdb::ExpressionBinder::BindExpression (this=this@entry=0x7fffffffb730, function=..., depth=depth@entry=0x0, expr_ptr=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/common/optional_ptr.hpp:43
#13 0x0000555555e728c0 in duckdb::ExpressionBinder::BindExpression (this=this@entry=0x7fffffffb730, expr=..., depth=depth@entry=0x0,
    root_expression=root_expression@entry=0x0) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:79
#14 0x0000555555e5361b in duckdb::BaseSelectBinder::BindExpression (this=0x7fffffffb730, expr_ptr=..., depth=0x0, root_expression=<optimized out>)
    at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder/base_select_binder.cpp:41
#15 0x0000555555e68b21 in duckdb::ExpressionBinder::Bind[abi:cxx11](duckdb::unique_ptr<duckdb::ParsedExpression, std::default_delete<duckdb::ParsedExpression>, true>&, unsigned long, bool) (this=0x7fffffffb730, expr=..., depth=0x0, root_expression=<optimized out>) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:264
#16 0x0000555555e68ceb in duckdb::ExpressionBinder::BindChild (this=this@entry=0x7fffffffb730, expr=..., depth=depth@entry=0x0, error="")
    at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:124
#17 0x0000555555df469e in duckdb::ExpressionBinder::BindFunction (this=0x7fffffffb730, function=..., func=..., depth=0x0) at /usr/include/c++/9/bits/stl_vector.h:1040
#18 0x0000555555df9b42 in duckdb::ExpressionBinder::BindExpression (this=this@entry=0x7fffffffb730, function=..., depth=depth@entry=0x0, expr_ptr=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/common/optional_ptr.hpp:43
#19 0x0000555555e728c0 in duckdb::ExpressionBinder::BindExpression (this=this@entry=0x7fffffffb730, expr=..., depth=depth@entry=0x0,
    root_expression=root_expression@entry=0x1) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:79
#20 0x0000555555e5361b in duckdb::BaseSelectBinder::BindExpression (this=0x7fffffffb730, expr_ptr=..., depth=0x0, root_expression=<optimized out>)
    at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder/base_select_binder.cpp:41
#21 0x0000555555e68b21 in duckdb::ExpressionBinder::Bind[abi:cxx11](duckdb::unique_ptr<duckdb::ParsedExpression, std::default_delete<duckdb::ParsedExpression>, true>&, unsigned long, bool) (this=0x7fffffffb730, expr=..., depth=0x0, root_expression=<optimized out>) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:264
#22 0x0000555555e6fc54 in duckdb::ExpressionBinder::Bind (this=this@entry=0x7fffffffb730, expr=..., result_type=result_type@entry=...,
    root_expression=root_expression@entry=0x1) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/expression_binder.cpp:218
#23 0x00005555564bf386 in duckdb::Binder::BindSelectNode (this=0x55555719ecc0, statement=..., from_table=...) at /usr/include/c++/9/bits/stl_vector.h:1040
#24 0x00005555564c041c in duckdb::Binder::BindNode (this=this@entry=0x55555719ecc0, statement=...) at /usr/include/c++/9/bits/move.h:74
#25 0x0000555555e77936 in duckdb::Binder::BindNode (this=0x55555719ecc0, node=...) at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/parser/query_node.hpp:88
#26 0x0000555555e77a3b in duckdb::Binder::Bind (this=0x55555719ecc0, node=...) at /home/luy70/Desktop/DBMSs/duckdb/src/planner/binder.cpp:159
#27 0x0000555555e0bc01 in duckdb::Binder::Bind (this=<optimized out>, stmt=...) at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/common/unique_ptr.hpp:19
#28 0x0000555555e724d5 in duckdb::Binder::Bind (this=<optimized out>, statement=...) at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/parser/sql_statement.hpp:57
#29 0x0000555555e7c03e in duckdb::Planner::CreatePlan (this=0x7fffffffc060, statement=...) at /usr/include/c++/9/bits/shared_ptr_base.h:1020
#30 0x0000555555e7c513 in duckdb::Planner::CreatePlan (this=this@entry=0x7fffffffc060, statement=...)
    at /home/luy70/Desktop/DBMSs/duckdb/src/include/duckdb/common/unique_ptr.hpp:30
#31 0x0000555555c35702 in duckdb::ClientContext::CreatePreparedStatement (this=0x555557299b00, lock=..., query=..., statement=..., values=...)
    at /usr/include/c++/9/bits/move.h:74
#32 0x0000555555c35d3e in duckdb::ClientContext::<lambda()>::operator() (__closure=0x5555572a0c80) at /usr/include/c++/9/bits/move.h:74
#33 std::_Function_handler<void(), duckdb::ClientContext::PrepareInternal(duckdb::ClientContextLock&, duckdb::unique_ptr<duckdb::SQLStatement, std::default_delete<duckdb::SQLStatement>, true>)::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/9/bits/std_function.h:300
#34 0x0000555555c28869 in std::function<void ()>::operator()() const (this=0x7fffffffc3a0) at /usr/include/c++/9/bits/std_function.h:683
#35 duckdb::ClientContext::RunFunctionInTransactionInternal(duckdb::ClientContextLock&, std::function<void ()> const&, bool) (this=0x555557299b00, lock=..., fun=...,
    requires_valid_transaction=<optimized out>) at /home/luy70/Desktop/DBMSs/duckdb/src/main/client_context.cpp:961
#36 0x0000555555c293ee in duckdb::ClientContext::PrepareInternal (this=0x555557299b00, lock=..., statement=...) at /usr/include/c++/9/bits/std_function.h:87
#37 0x0000555555c40cd0 in duckdb::ClientContext::Prepare (this=0x555557299b00, statement=...) at /usr/include/c++/9/bits/unique_ptr.h:360
#38 0x0000555555c40d86 in duckdb::Connection::Prepare (this=<optimized out>, statement=...) at /usr/include/c++/9/bits/move.h:74
#39 0x0000555555843fcd in duckdb_shell_sqlite3_prepare_v2 (db=0x55555719e780,
    zSql=0x55555719f400 "SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL SECONDS [ ] [ ] :: SETOF NCHAR ARRAY :: FLOAT ; ", nByte=<optimized out>,
    ppStmt=0x7fffffffc7a8, pzTail=0x7fffffffc7b0) at /usr/include/c++/9/bits/move.h:74
#40 0x000055555582ab1a in shell_exec (pArg=<optimized out>,
    zSql=0x55555719f400 "SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL SECONDS [ ] [ ] :: SETOF NCHAR ARRAY :: FLOAT ; ", pzErrMsg=0x7fffffffc8a8)
    at /home/luy70/Desktop/DBMSs/duckdb/tools/shell/shell.c:13145
#41 0x000055555582c9fd in runOneSqlLine (p=0x7fffffffcab0,
    zSql=0x55555719f400 "SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL SECONDS [ ] [ ] :: SETOF NCHAR ARRAY :: FLOAT ; ", in=0x0, startline=0x1)
    at /home/luy70/Desktop/DBMSs/duckdb/tools/shell/shell.c:19658
#42 0x0000555555835099 in process_input (p=0x7fffffffcab0) at /home/luy70/Desktop/DBMSs/duckdb/tools/shell/shell.c:19776
#43 0x0000555555815148 in main (argc=argc@entry=0x1, argv=argv@entry=0x7fffffffdde8) at /home/luy70/Desktop/DBMSs/duckdb/tools/shell/shell.c:20594
#44 0x00007ffff7a6f083 in __libc_start_main (main=0x555555814510 <main>, argc=0x1, argv=0x7fffffffdde8, init=<optimized out>, fini=<optimized out>,
    rtld_fini=<optimized out>, stack_end=0x7fffffffddd8) at ../csu/libc-start.c:308
#45 0x000055555581879e in _start () at /usr/include/x86_64-linux-gnu/bits/stdio2.h:100

To Reproduce

  1. Clone the DuckDB Git from the official repo.
  2. Checkout to either the latest main or release version: v0.9.2.
  3. Compile the DuckDB binary by using either make reldebug or make debug.
  4. Run the compiled DuckDB and input the following SQL:
SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL SECONDS [ ] [ ] :: SETOF NCHAR ARRAY :: FLOAT ; 
  1. Observe and log the crash information.

OS:

Ubuntu 20.04 LTS

DuckDB Version:

v0.9.2

DuckDB Client:

DuckDB official command line host

Full Name:

Yu Liang

Affiliation:

The Pennsylvania State University

Have you tried this on the latest main branch?

I have tested with a main build

Have you tried the steps to reproduce? Do they include all relevant data and configuration? Does the issue you report still appear there?

  • Yes, I have
@hawkfish
Copy link
Contributor

hawkfish commented Jan 4, 2024

After fixing the issue, the error I get is:

Binder Error: No function matches the given name and argument types '/(FLOAT)'. You might need to add explicit type casts.
	Candidate functions:
	/(FLOAT, FLOAT) -> FLOAT
	/(DOUBLE, DOUBLE) -> DOUBLE
	/(INTERVAL, BIGINT) -> INTERVAL

LINE 1: SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL ...

so you might want to check what you are doing here (this looks like generated SQL?)

hawkfish added a commit to hawkfish/duckdb that referenced this issue Jan 4, 2024
Don't copy the data for a NULL constant list
as it may not exist.

fixes: duckdb#10140
fixes: duckdblabs/duckdb-internal#1006
Mytherin added a commit that referenced this issue Jan 5, 2024
@SteveLeungYL
Copy link
Author

After fixing the issue, the error I get is:

Binder Error: No function matches the given name and argument types '/(FLOAT)'. You might need to add explicit type casts.
	Candidate functions:
	/(FLOAT, FLOAT) -> FLOAT
	/(DOUBLE, DOUBLE) -> DOUBLE
	/(INTERVAL, BIGINT) -> INTERVAL

LINE 1: SELECT DISTINCT OPERATOR ( / ) + ARRAY [ ] :: INTERVAL ...

so you might want to check what you are doing here (this looks like generated SQL?)

Thank you for the super quick fixing.

The query does look ill-formed and doesn't make sense in the real-world usage. However, these kinds of PoCs/crashes can still be utilized by malicious application attackers if they successfully obtain the SQL interface, assuming DuckDB is embedded into many critical applications. Therefore, we decided to report this bug here after we detected it.

@hawkfish
Copy link
Contributor

hawkfish commented Jan 5, 2024

The query does look ill-formed and doesn't make sense in the real-world usage. However, these kinds of PoCs/crashes can still be utilized by malicious application attackers if they successfully obtain the SQL interface, assuming DuckDB is embedded into many critical applications. Therefore, we decided to report this bug here after we detected it.

Thanks - we appreciate it! I wasn't complaining, just letting you know what might be happening on your end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants