Merge lp:~zorba-coders/zorba/bug907872 into lp:zorba

Proposed by Matthias Brantner
Status: Merged
Approved by: Markos Zaharioudakis
Approved revision: 10592
Merged at revision: 10599
Proposed branch: lp:~zorba-coders/zorba/bug907872
Merge into: lp:zorba
Diff against target: 200 lines (+106/-3)
6 files modified
ChangeLog (+2/-1)
src/runtime/core/fncall_iterator.cpp (+3/-1)
test/unit/CMakeLists.txt (+2/-0)
test/unit/ext_main3.xq (+21/-0)
test/unit/ext_mod2.xq (+19/-0)
test/unit/external_function.cpp (+59/-1)
To merge this branch: bzr merge lp:~zorba-coders/zorba/bug907872
Reviewer Review Type Date Requested Status
Markos Zaharioudakis Approve
Matthias Brantner Approve
Review via email: mp+86738@code.launchpad.net

Commit message

fix for bug #907872 (segfault when returning an input ItemSequence from an external function)

Description of the change

fix for bug #907872 (segfault when returning an input ItemSequence from an external function). ExtFunctionCallIterator doesn't have the exclusive ownership over the ItemSequences such that their lifecycle can exceed the lifetime of the iterator itself.

To post a comment you must log in.
Revision history for this message
Matthias Brantner (matthias-brantner) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job bug907872-2011-12-22T19-18-00.125Z is finished. The final status was:

All tests succeeded!

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1. Got: 1 Approve, 2 Pending.

Revision history for this message
Markos Zaharioudakis (markos-za) wrote :

Matthias, I cannot see how the example you added illustrates the case where an ExtFuncArgItemSequence must live longer than the ExtFunctionCallIterator who created it. In fact, I tried the example without your modification in fncall_iterator.cpp and it worked fine. What am I missing?

Revision history for this message
Matthias Brantner (matthias-brantner) wrote :

Did you also try the example (without my fix) and valgrind? I don't get a crash either but valgrind shows that there are serious problems:

==12383== Invalid read of size 4
==12383== at 0x448BDFF: zorba::SmartPtr<zorba::ItemSequence>::~SmartPtr() (smart_ptr.h:82)
==12383== by 0x4D25F43: zorba::ExtFunctionCallIteratorState::~ExtFunctionCallIteratorState() (fncall_iterator.cpp:625)
==12383== by 0x4D2FE87: zorba::StateTraitsImpl<zorba::ExtFunctionCallIteratorState>::destroyState(zorba::PlanState&, unsigned int) (plan_iterator.h:283)
==12383== by 0x4D2FE4D: zorba::NaryBaseIterator<zorba::ExtFunctionCallIterator, zorba::ExtFunctionCallIteratorState>::closeImpl(zorba::PlanState&) (narybase.h:164)
==12383== by 0x4D2F815: zorba::Batcher<zorba::ExtFunctionCallIterator>::close(zorba::PlanState&) (plan_iterator.h:563)
==12383== by 0x4CAFC27: zorba::PlanWrapper::close() (plan_wrapper.cpp:179)
==12383== by 0x4457EFB: zorba::XQueryImpl::execute(std::ostream&, Zorba_SerializerOptions const*) (xqueryimpl.cpp:1124)
==12383== by 0x4459B13: zorba::operator<<(std::ostream&, zorba::SmartPtr<zorba::XQuery> const&) (xqueryimpl.cpp:1580)
==12383== by 0x8068B83: external_function_test_4(zorba::Zorba*) (external_function.cpp:361)
==12383== by 0x8068E6B: external_function(int, char**) (external_function.cpp:407)
==12383== by 0x80613C4: main (UnitTests.cpp:270)
==12383== Address 0x7e00e28 is 0 bytes inside a block of size 24 free'd
==12383== at 0x4025907: operator delete(void*) (vg_replace_malloc.c:387)
==12383== by 0x4D2F3F5: zorba::ExtFuncArgItemSequence::~ExtFuncArgItemSequence() (fncall_iterator.cpp:539)
==12383== by 0x4D25F16: zorba::ExtFunctionCallIteratorState::~ExtFunctionCallIteratorState() (fncall_iterator.cpp:633)
==12383== by 0x4D2FE87: zorba::StateTraitsImpl<zorba::ExtFunctionCallIteratorState>::destroyState(zorba::PlanState&, unsigned int) (plan_iterator.h:283)
==12383== by 0x4D2FE4D: zorba::NaryBaseIterator<zorba::ExtFunctionCallIterator, zorba::ExtFunctionCallIteratorState>::closeImpl(zorba::PlanState&) (narybase.h:164)
==12383== by 0x4D2F815: zorba::Batcher<zorba::ExtFunctionCallIterator>::close(zorba::PlanState&) (plan_iterator.h:563)
==12383== by 0x4CAFC27: zorba::PlanWrapper::close() (plan_wrapper.cpp:179)
==12383== by 0x4457EFB: zorba::XQueryImpl::execute(std::ostream&, Zorba_SerializerOptions const*) (xqueryimpl.cpp:1124)
==12383== by 0x4459B13: zorba::operator<<(std::ostream&, zorba::SmartPtr<zorba::XQuery> const&) (xqueryimpl.cpp:1580)
==12383== by 0x8068B83: external_function_test_4(zorba::Zorba*) (external_function.cpp:361)
==12383== by 0x8068E6B: external_function(int, char**) (external_function.cpp:407)
==12383== by 0x80613C4: main (UnitTests.cpp:270)

Revision history for this message
Markos Zaharioudakis (markos-za) :
review: Approve
Revision history for this message
Markos Zaharioudakis (markos-za) wrote :
Download full text (3.5 KiB)

The ExtFuncArgItemSequence cannot live longer than the ExtFunctionCallIterator who created it, because it is just a wrapper over a child of the ExtFunctionCallIterator, and if the ExtFunctionCallIterator is destroyed, its children are destroyed as well.

The real problem is that the ExtFuncArgItemSequence is assigned to an ItemSequence_t (the return value of the evaluate() method). Since ItemSequence_t is a smart pointer, it will destroy the ExtFuncArgItemSequence when itself is destroyed. Later, when the ExtFunctionCallIterator is closed, it will also try to destroy the ExtFuncArgItemSequence.

Your fix solves this problem, so I have approved it.

> Did you also try the example (without my fix) and valgrind? I don't get a
> crash either but valgrind shows that there are serious problems:
>
> ==12383== Invalid read of size 4
> ==12383== at 0x448BDFF: zorba::SmartPtr<zorba::ItemSequence>::~SmartPtr()
> (smart_ptr.h:82)
> ==12383== by 0x4D25F43:
> zorba::ExtFunctionCallIteratorState::~ExtFunctionCallIteratorState()
> (fncall_iterator.cpp:625)
> ==12383== by 0x4D2FE87: zorba::StateTraitsImpl<zorba::ExtFunctionCallIterat
> orState>::destroyState(zorba::PlanState&, unsigned int) (plan_iterator.h:283)
> ==12383== by 0x4D2FE4D:
> zorba::NaryBaseIterator<zorba::ExtFunctionCallIterator,
> zorba::ExtFunctionCallIteratorState>::closeImpl(zorba::PlanState&)
> (narybase.h:164)
> ==12383== by 0x4D2F815:
> zorba::Batcher<zorba::ExtFunctionCallIterator>::close(zorba::PlanState&)
> (plan_iterator.h:563)
> ==12383== by 0x4CAFC27: zorba::PlanWrapper::close() (plan_wrapper.cpp:179)
> ==12383== by 0x4457EFB: zorba::XQueryImpl::execute(std::ostream&,
> Zorba_SerializerOptions const*) (xqueryimpl.cpp:1124)
> ==12383== by 0x4459B13: zorba::operator<<(std::ostream&,
> zorba::SmartPtr<zorba::XQuery> const&) (xqueryimpl.cpp:1580)
> ==12383== by 0x8068B83: external_function_test_4(zorba::Zorba*)
> (external_function.cpp:361)
> ==12383== by 0x8068E6B: external_function(int, char**)
> (external_function.cpp:407)
> ==12383== by 0x80613C4: main (UnitTests.cpp:270)
> ==12383== Address 0x7e00e28 is 0 bytes inside a block of size 24 free'd
> ==12383== at 0x4025907: operator delete(void*) (vg_replace_malloc.c:387)
> ==12383== by 0x4D2F3F5:
> zorba::ExtFuncArgItemSequence::~ExtFuncArgItemSequence()
> (fncall_iterator.cpp:539)
> ==12383== by 0x4D25F16:
> zorba::ExtFunctionCallIteratorState::~ExtFunctionCallIteratorState()
> (fncall_iterator.cpp:633)
> ==12383== by 0x4D2FE87: zorba::StateTraitsImpl<zorba::ExtFunctionCallIterat
> orState>::destroyState(zorba::PlanState&, unsigned int) (plan_iterator.h:283)
> ==12383== by 0x4D2FE4D:
> zorba::NaryBaseIterator<zorba::ExtFunctionCallIterator,
> zorba::ExtFunctionCallIteratorState>::closeImpl(zorba::PlanState&)
> (narybase.h:164)
> ==12383== by 0x4D2F815:
> zorba::Batcher<zorba::ExtFunctionCallIterator>::close(zorba::PlanState&)
> (plan_iterator.h:563)
> ==12383== by 0x4CAFC27: zorba::PlanWrapper::close() (plan_wrapper.cpp:179)
> ==12383== by 0x4457EFB: zorba::XQueryImpl::execute(std::ostream&,
> Zorba_SerializerOptions const*) (xqueryimpl.cpp:1124)
> ==12383== by 0x4459B13...

Read more...

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job bug907872-2012-01-03T13-15-02.06Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2011-12-22 14:14:53 +0000
3+++ ChangeLog 2011-12-22 19:16:24 +0000
4@@ -10,7 +10,8 @@
5 * Added index management function to the C++ api's StaticCollectionManager.
6 * Fixed bug #905041 (allow for the default element and function namespaces to be
7 set multiple times via the c++ api).
8- * Fixed bug #905050 (setting and getting the context item type via the c++ api)
9+ * Fixed bug #907872 (segfault when returning an input ItemSequence from an external function).
10+ * Fixed bug #905050 (setting and getting the context item type via the c++ api).
11 * Added createDayTimeDuration, createYearMonthDuration, createDocumentNode, createCommentNode, createPiNode to api's ItemFactory.
12
13 version 2.1
14
15=== modified file 'src/runtime/core/fncall_iterator.cpp'
16--- src/runtime/core/fncall_iterator.cpp 2011-12-21 14:40:33 +0000
17+++ src/runtime/core/fncall_iterator.cpp 2011-12-22 19:16:24 +0000
18@@ -630,7 +630,7 @@
19
20 for (csize i = 0; i < n; ++i)
21 {
22- delete m_extArgs[i];
23+ m_extArgs[i]->removeReference();
24 }
25 }
26
27@@ -737,6 +737,8 @@
28 for(ulong i = 0; i < n; ++i)
29 {
30 state->m_extArgs[i] = new ExtFuncArgItemSequence(theChildren[i], planState);
31+ // the iterator does not have exlcusive ownership over the sequences
32+ state->m_extArgs[i]->addReference();
33 }
34 }
35
36
37=== modified file 'test/unit/CMakeLists.txt'
38--- test/unit/CMakeLists.txt 2011-12-21 14:40:33 +0000
39+++ test/unit/CMakeLists.txt 2011-12-22 19:16:24 +0000
40@@ -28,8 +28,10 @@
41
42 #belongs to test external_function.cpp
43 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ext_mod.xq ${CMAKE_CURRENT_BINARY_DIR}/ext_mod.xq)
44+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ext_mod2.xq ${CMAKE_CURRENT_BINARY_DIR}/ext_mod2.xq)
45 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ext_main.xq ${CMAKE_CURRENT_BINARY_DIR}/ext_main.xq)
46 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ext_main2.xq ${CMAKE_CURRENT_BINARY_DIR}/ext_main2.xq)
47+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ext_main3.xq ${CMAKE_CURRENT_BINARY_DIR}/ext_main3.xq)
48
49 #belongs to test no_folding.cpp
50 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/fold_mod1.xq ${CMAKE_CURRENT_BINARY_DIR}/fold_mod1.xq)
51
52=== added file 'test/unit/ext_main3.xq'
53--- test/unit/ext_main3.xq 1970-01-01 00:00:00 +0000
54+++ test/unit/ext_main3.xq 2011-12-22 19:16:24 +0000
55@@ -0,0 +1,21 @@
56+(:
57+ : Copyright 2006-2009 The FLWOR Foundation.
58+ :
59+ : Licensed under the Apache License, Version 2.0 (the "License");
60+ : you may not use this file except in compliance with the License.
61+ : You may obtain a copy of the License at
62+ :
63+ : http://www.apache.org/licenses/LICENSE-2.0
64+ :
65+ : Unless required by applicable law or agreed to in writing, software
66+ : distributed under the License is distributed on an "AS IS" BASIS,
67+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68+ : See the License for the specific language governing permissions and
69+ : limitations under the License.
70+:)
71+
72+
73+import module namespace ext = "http://www.zorba-xquery.com/m" at "file:///${CMAKE_CURRENT_BINARY_DIR}/ext_mod2.xq";
74+
75+
76+ext:bar4(for $i in 1 to 10 return $i)
77
78=== added file 'test/unit/ext_mod2.xq'
79--- test/unit/ext_mod2.xq 1970-01-01 00:00:00 +0000
80+++ test/unit/ext_mod2.xq 2011-12-22 19:16:24 +0000
81@@ -0,0 +1,19 @@
82+(:
83+ : Copyright 2006-2009 The FLWOR Foundation.
84+ :
85+ : Licensed under the Apache License, Version 2.0 (the "License");
86+ : you may not use this file except in compliance with the License.
87+ : You may obtain a copy of the License at
88+ :
89+ : http://www.apache.org/licenses/LICENSE-2.0
90+ :
91+ : Unless required by applicable law or agreed to in writing, software
92+ : distributed under the License is distributed on an "AS IS" BASIS,
93+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
94+ : See the License for the specific language governing permissions and
95+ : limitations under the License.
96+:)
97+
98+module namespace ext = "http://www.zorba-xquery.com/m";
99+
100+declare function ext:bar4($s as item()*) as item()* external;
101
102=== modified file 'test/unit/external_function.cpp'
103--- test/unit/external_function.cpp 2011-10-10 19:29:05 +0000
104+++ test/unit/external_function.cpp 2011-12-22 19:16:24 +0000
105@@ -125,6 +125,18 @@
106 }
107 };
108
109+class MySimpleExternalFunction4 : public NonContextualExternalFunction
110+{
111+public:
112+ String getURI() const { return "http://www.zorba-xquery.com/m"; }
113+
114+ String getLocalName() const { return "bar4"; }
115+
116+ ItemSequence_t evaluate(const ExternalFunction::Arguments_t& args) const
117+ {
118+ return args[0];
119+ }
120+};
121
122 class MyExternalModule : public ExternalModule
123 {
124@@ -132,6 +144,7 @@
125 MySimpleExternalFunction bar;
126 MySimpleExternalFunction2 bar2;
127 MySimpleExternalFunction3 bar3;
128+ MySimpleExternalFunction4 bar4;
129
130 public:
131 String getURI() const { return "http://www.zorba-xquery.com/m"; }
132@@ -140,8 +153,10 @@
133 {
134 if (aLocalname == "bar")
135 return const_cast<MySimpleExternalFunction*>(&bar);
136- if (aLocalname == "bar3")
137+ else if (aLocalname == "bar3")
138 return const_cast<MySimpleExternalFunction3*>(&bar3);
139+ else if (aLocalname == "bar4")
140+ return const_cast<MySimpleExternalFunction4*>(&bar4);
141 else
142 return const_cast<MySimpleExternalFunction2*>(&bar2);
143 }
144@@ -327,6 +342,42 @@
145 return true;
146 }
147
148+bool
149+external_function_test_4(Zorba* aZorba)
150+{
151+ try
152+ {
153+ std::ifstream lIn("ext_main3.xq");
154+ assert(lIn.good());
155+ std::ostringstream lOut;
156+ MyExternalModule lMod;
157+
158+ StaticContext_t lSctx = aZorba->createStaticContext();
159+ lSctx->registerModule(&lMod);
160+
161+ {
162+ XQuery_t lQuery = aZorba->compileQuery(lIn, lSctx);
163+
164+ std::cout << lQuery << std::endl;
165+ }
166+ }
167+ catch (XQueryException& qe)
168+ {
169+ std::cerr << qe << std::endl;
170+ return false;
171+ }
172+ catch (ZorbaException& e)
173+ {
174+ std::cerr << e << std::endl;
175+ return false;
176+ }
177+ catch (...)
178+ {
179+ return false;
180+ }
181+ return true;
182+}
183+
184
185 int
186 external_function(int argc, char* argv[])
187@@ -352,6 +403,13 @@
188 return 3;
189 }
190
191+ std::cout << "executing external_function_test_4" << std::endl;
192+ if (!external_function_test_4(lZorba))
193+ {
194+ return 4;
195+ }
196+
197+
198 lZorba->shutdown();
199 zorba::StoreManager::shutdownStore(lStore);
200 return 0;

Subscribers

People subscribed via source and target branches