Certain keys in a query can cause segmentation faults

Description

https://github.com/couchbase/couchbase-lite-core/issues/864

The most simple way to trigger bug:

 

{{$ ./cblite /tmp/sync_docs.cblite2
Opened read-only database /tmp/sync_docs.cblite2/
(cblite) query {"WHAT": [".departure_time"], "WHERE": ["AND", ["=",[".type"], "MyDoc"], ["=", ["_.id"], "6ff2ffc3-3b73-44e2-aff2-dfccefd80ad5"]]}
Segmentation fault (core dumped)}}

But bug is not related to cblite tool, it is just simple way to trigger it.
backtrace of cblite:

 

{{#0 0x000055c8582207ce in fleece::impl::Value::tag() const ()
(gdb) bt
#0 0x000055c8582207ce in fleece::impl::Value::tag() const ()
#1 0x000055c85842ac9a in fleece::impl::Value::type() const ()
#2 0x000055c85821a687 in litecore::QueryParser::parseNode(fleece::impl::Value const*) ()
#3 0x000055c85821ccae in litecore::QueryParser::objectPropertyOp(fleece::slice, fleece::impl::Array::iterator&) ()
#4 0x000055c85821da1c in litecore::QueryParser::fallbackOp(fleece::slice, fleece::impl::Array::iterator&) ()
#5 0x000055c85821ac27 in litecore::QueryParser::handleOperation(litecore::QueryParser::Operation const*, fleece::slice, fleece::impl::Array::iterator&) ()
#6 0x000055c85821ab32 in litecore::QueryParser::parseOpNode(fleece::impl::Array const*) ()
#7 0x000055c85821a7ee in litecore::QueryParser::parseNode(fleece::impl::Value const*) ()
#8 0x000055c85821a87d in litecore::QueryParser::parseCollatableNode(fleece::impl::Value const*) ()
#9 0x000055c85821b0e6 in litecore::QueryParser::infixOp(fleece::slice, fleece::impl::Array::iterator&) ()
#10 0x000055c85821ac27 in litecore::QueryParser::handleOperation(litecore::QueryParser::Operation const*, fleece::slice, fleece::impl::Array::iterator&) ()
#11 0x000055c85821ab32 in litecore::QueryParser::parseOpNode(fleece::impl::Array const*) ()
#12 0x000055c85821a7ee in litecore::QueryParser::parseNode(fleece::impl::Value const*) ()
#13 0x000055c85821a87d in litecore::QueryParser::parseCollatableNode(fleece::impl::Value const*) ()
#14 0x000055c85821b0e6 in litecore::QueryParser::infixOp(fleece::slice, fleece::impl::Array::iterator&) ()
#15 0x000055c85821ac27 in litecore::QueryParser::handleOperation(litecore::QueryParser::Operation const*, fleece::slice, fleece::impl::Array::iterator&) ()
#16 0x000055c85821ab32 in litecore::QueryParser::parseOpNode(fleece::impl::Array const*) ()
#17 0x000055c85821a7ee in litecore::QueryParser::parseNode(fleece::impl::Value const*) ()
#18 0x000055c858219453 in litecore::QueryParser::writeWhereClause(fleece::impl::Value const*) ()
#19 0x000055c858218d35 in litecore::QueryParser::writeSelect(fleece::impl::Value const*, fleece::impl::Dict const*) ()
#20 0x000055c85821896b in litecore::QueryParser::writeSelect(fleece::impl::Dict const*) ()
#21 0x000055c858218788 in litecore::QueryParser::parse(fleece::impl::Value const*) ()
#22 0x000055c8582186ae in litecore::QueryParser::parseJSON(fleece::slice) ()
#23 0x000055c85826983f in litecore::SQLiteQuery::SQLiteQuery(litecore::SQLiteKeyStore&, fleece::slice, litecore::QueryLanguage) ()
#24 0x000055c858268d3a in litecore::SQLiteKeyStore::compileQuery(fleece::slice, litecore::QueryLanguage) ()
#25 0x000055c8581eec23 in c4Query::c4Query(c4Internal::Database*, unsigned int, FLSlice) ()
#26 0x000055c8581ecba8 in c4query_new2::{lambda()#1}::operator()() const ()
#27 0x000055c8581ee02d in c4Query* fleece::function_ref<c4Query* ()>::callback_fn<c4query_new2::{lambda()#1}>(long) ()
#28 0x000055c8581f022c in fleece::function_ref<c4Query* ()>::operator()() const ()
#29 0x000055c8581efb40 in c4Query* c4Internal::tryCatch<c4Query*>(C4Error*, fleece::function_ref<c4Query* ()>) ()
#30 0x000055c8581ecccd in c4query_new2 ()}}

backtrace of my program, which uses couchbase-lite-core directly:

 

{{#0 0x00007f8929a0d582 in fleece::impl::Value::tag (this=0x0)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/vendor/fleece/Fleece/Core/Value.hh:211
#1 0x00007f8929c25ad2 in fleece::impl::Value::type (this=0x0)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/vendor/fleece/Fleece/Core/Value.cc:71
#2 0x00007f8929a10a41 in litecore::QueryParser::parseNode (this=0x7f8926a29ca0, node=0x0)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:547
#3 0x00007f8929a13098 in litecore::QueryParser::objectPropertyOp (this=0x7f8926a29ca0, op=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:930
#4 0x00007f8929a13e06 in litecore::QueryParser::fallbackOp (this=0x7f8926a29ca0, op=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:1063
#5 0x00007f8929a10fe1 in litecore::QueryParser::handleOperation (this=0x7f8926a29ca0, op=0x7f8929e35610 <litecore::QueryParser::kOperationList+1872>, actualOperator=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:627
#6 0x00007f8929a10eec in litecore::QueryParser::parseOpNode (this=0x7f8926a29ca0, node=0x7f891803b680)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:612
#7 0x00007f8929a10ba8 in litecore::QueryParser::parseNode (this=0x7f8926a29ca0, node=0x7f891803b680)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:563
#8 0x00007f8929a10c37 in litecore::QueryParser::parseCollatableNode (this=0x7f8926a29ca0, node=0x7f891803b680)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:576
#9 0x00007f8929a11486 in litecore::QueryParser::infixOp (this=0x7f8926a29ca0, op=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:683
#10 0x00007f8929a10fe1 in litecore::QueryParser::handleOperation (this=0x7f8926a29ca0, op=0x7f8929e35220 <litecore::QueryParser::kOperationList+864>, actualOperator=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:627
#11 0x00007f8929a10eec in litecore::QueryParser::parseOpNode (this=0x7f8926a29ca0, node=0x7f891803b6aa)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:612
#12 0x00007f8929a10ba8 in litecore::QueryParser::parseNode (this=0x7f8926a29ca0, node=0x7f891803b6aa)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:563
#13 0x00007f8929a10c37 in litecore::QueryParser::parseCollatableNode (this=0x7f8926a29ca0, node=0x7f891803b6aa)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:576
#14 0x00007f8929a11486 in litecore::QueryParser::infixOp (this=0x7f8926a29ca0, op=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:683
#15 0x00007f8929a10fe1 in litecore::QueryParser::handleOperation (this=0x7f8926a29ca0, op=0x7f8929e35460 <litecore::QueryParser::kOperationList+1440>, actualOperator=..., operands=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:627
#16 0x00007f8929a10eec in litecore::QueryParser::parseOpNode (this=0x7f8926a29ca0, node=0x7f891803b6b2)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:612
#17 0x00007f8929a10ba8 in litecore::QueryParser::parseNode (this=0x7f8926a29ca0, node=0x7f891803b6b2)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:563
#18 0x00007f8929a0f80d in litecore::QueryParser::writeWhereClause (this=0x7f8926a29ca0, where=0x7f891803b6b2)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:344
#19 0x00007f8929a0f0ef in litecore::QueryParser::writeSelect (this=0x7f8926a29ca0, where=0x7f891803b6b2, operands=0x7f891803b6ba)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:269
#20 0x00007f8929a0ed25 in litecore::QueryParser::writeSelect (this=0x7f8926a29ca0, operands=0x7f891803b6ba)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:219
#21 0x00007f8929a0eb42 in litecore::QueryParser::parse (this=0x7f8926a29ca0, expression=0x7f891803b6ba)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:192
#22 0x00007f8929a0ea68 in litecore::QueryParser::parseJSON (this=0x7f8926a29ca0, expressionJSON=...)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/QueryParser.cc:183
#23 0x00007f8929a60d67 in litecore::SQLiteQuery::SQLiteQuery (this=0x7f8918025270, keyStore=..., queryStr=..., language=litecore::QueryLanguage::kJSON)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/SQLiteQuery.cc:81
#24 0x00007f8929a6390c in litecore::SQLiteKeyStore::compileQuery (this=0x7f8918023f10, selectorExpression=..., language=litecore::QueryLanguage::kJSON)
at /home/evgeniy/.cargo/git/checkouts/couchbase-lite-rust-a552ad01d6a5c3d0/73911da/couchbase-lite-core-sys/couchbase-lite-core/LiteCore/Query/SQLiteQuery.cc:501
#25 0x00007f89299e0d7c in c4Query::c4Query (this=0x7f8918040780, db=0x7f8918000d30, language=0, queryExpression=...)}}

The problem in swap of _ and . in ["_.id"], it would be nice to get error instead of segmentation fault in this case.

From -

According to the backtrace, QueryParser.cc:547 is dereferencing a null Value*.
The caller of that is objectPropertyOp, whose comment reads Handles object (dict) property accessors, e.g. ["_.", [...], "prop"] --> fl_property(..., "prop").
That method calls parseNode(operands[0]); before checking that operands is non-empty ... oops. A lot of the xxxOp methods have their operand count checked before they're called, but not this one.

This could be fixed by adding at the start of the method:
require(!operands.empty, "Missing receiver for object property");
 

Activity

Show:

Jens Alfke February 4, 2020 at 10:54 PM

Fixed in LiteCore commit 3126e276.

Fixed
Pinned fields
Click on the next to a field label to start pinning.

Details

Assignee

Reporter

Story Points

Components

Fix versions

Affects versions

Priority

Instabug

Open Instabug

PagerDuty

Sentry

Zendesk Support

Created November 7, 2019 at 1:54 AM
Updated March 7, 2020 at 12:42 AM
Resolved February 4, 2020 at 10:54 PM
Instabug