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

Using row::move_as while iterating rowset yields segmentation fault #1144

Open
Krzmbrzl opened this issue Apr 21, 2024 · 3 comments · May be fixed by #1145
Open

Using row::move_as while iterating rowset yields segmentation fault #1144

Krzmbrzl opened this issue Apr 21, 2024 · 3 comments · May be fixed by #1145

Comments

@Krzmbrzl
Copy link
Contributor

Originally reported by @avpalienko in #1141 (comment)

When applying the following patch to the common-tests.h file, the move_as test case will crash due to a segmentation fault:

diff --git a/tests/common-tests.h b/tests/common-tests.h
index d2b8fb42..ffc80fc6 100644
--- a/tests/common-tests.h
+++ b/tests/common-tests.h
@@ -6779,7 +6779,7 @@ TEST_CASE_METHOD(common_tests, "BLOB", "[core][blob]")
         }
         SECTION("move_as")
         {
-            soci::rowset< soci::row > rowSet = (sql.prepare << "select b from soci_test where id=:id", soci::use(id));
+            soci::rowset< soci::row > rowSet = (sql.prepare << "select b from soci_test where id=:id union all select b from soci_test where id=:id", soci::use(id, "id"));
             bool containedData = false;
             for (auto it = rowSet.begin(); it != rowSet.end(); ++it)
             {

The issue was originally reported to happen with Oracle, but I was also able to reproduce it with SQLite3, indicating that the issue is not backend-specific.

@Krzmbrzl
Copy link
Contributor Author

The problem seems to boil down to this:

  • the row object inside the rowset seems to be reused across different data fetches (loop iterations)
  • the row object is (seemingly) only initialized when first creating the rowset object (by binding the contained statement to the row in rowset's constructor)
  • when using move_as the respective entry inside row's holders gets into an invalid state. In case of a blob that corresponds to an uninitialized blob object (one where the backend pointer is nullptr)
  • In the next iteration, the statement wants to write data into the previously bound objects, including those that have been moved from and are thus in an invalid state
  • Trying to write data into an uninitialized blob dereferences the nullptr backend resulting in the segmentation fault

Therefore, the fix for this issue would be to find a way to let the row object know about invalidated holders, which should cause it to reinitialize them before trying to use them for data binding.

@Krzmbrzl Krzmbrzl changed the title rowset::move_as can lead to segmentation faults Using row::move_as while iterating rowset yields segmentation fault Apr 21, 2024
@Krzmbrzl Krzmbrzl linked a pull request Apr 21, 2024 that will close this issue
@avpalienko
Copy link

May be we could use shared_ptr inside the "row" class and eliminate move_as altogether ?

@Krzmbrzl
Copy link
Contributor Author

Nah, the get function cant return a pointer. That'd be inconsistent.
Besides, this wouldn't really solve the underlying problem. If the user moves from the dereferenced pointer, we're back at square one with the row object being broken.

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

Successfully merging a pull request may close this issue.

2 participants