I have identified another bug and prepared a patch for
dbd_mysql/dbd_msql. The purpose of result->currowidx was not totally
clear-cut, so I am posting this patch for potential comments.


parent 1619049a1e0eb018cdc8490f3cf344b4f2f53b0f ()
commit 537c2673f36465c2700829130da4054f53354a00
Author: Jan Engelhardt <jeng...@inai.de>
Date:   Thu May 1 18:04:47 2014 +0200

dbd_mysql, dbd_msql: resolve bogus seeking and a crash

I have a query result that, when iteratively seeked with
dbi_result_next_row() and read with dbi_result_get_string(), yields
these 15 values (1-based row indices shown in parentheses):

        B-W(1) BAY(2) BER(3) BRE(4) HAM(5) HES(6) M-V(7) NDS(8)
        NRW(9) RLP(10) SAR(11) SAC(12) S-A(13) S-H(14) THU(15)

Now, when using dbi_result_seek_row() to seek to arbitrary rows
(given in parentheses), dbi_result_get_string() can return incorrect
values. In particular, I have observed:

        B-W(1) S-H(14) B-W(1) THU(2)

What happens:

* row 1 is not already present, dbd_goto_row(1) is executed,
  the row data retrieved, and result->currowidx set to 1
* row 14 is not already present, a goto_row(14) is executed,
  the row data retrieved, and result->currowidx set to 14
* row 1 is already present, result->currowidx set to 1
* row 2 is not already present, dbd_goto_row(2) is NOT executed,
  because of rowidx == currowidx + 1 [2 == 2].
  So the next mysql row fetched is row 15, rather than 2.

Now, if my seek order was {1, 15, 1, 2}, then mysql_fetch_row()
called from function dbd_mysql.c:_get_row_data() will return NULL
because there are no more rows. There will be a subsequent NULL
dereference and crash.

It seems that result->currowidx is a high-level pointer, and is not
synchronized to the current DBD row pointer.

As such, these checks should be killed and a goto_row always
performed when so requested; the other DBD backends do the same.

After applying this patch, the seeked results correctly yield:

        B-W(1) S-H(14) B-W(1) BAY(2)
---
 drivers/msql/dbd_msql.c   | 7 +++----
 drivers/mysql/dbd_mysql.c | 5 ++---
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/msql/dbd_msql.c b/drivers/msql/dbd_msql.c
index d8edd50..f3709c4 100644
--- a/drivers/msql/dbd_msql.c
+++ b/drivers/msql/dbd_msql.c
@@ -149,11 +149,8 @@ int dbd_free_query(dbi_result_t *result)
 
 int dbd_goto_row(dbi_result_t *result, unsigned long long rowidx, unsigned 
long long currowidx) 
 {
-  if (rowidx != currowidx+1) {
     msqlDataSeek((m_result *)result->result_handle, rowidx);
-  }
-  /* else: nothing to do, next fetch will fetch the desired row */
-  return 1;
+    return 1;
 }
 
 
@@ -462,6 +459,8 @@ void _get_row_data(dbi_result_t *result, dbi_row_t *row, 
unsigned long long rowi
   
        msqlDataSeek(_res, rowidx);
        _row = msqlFetchRow(_res);
+       if (_row == NULL)
+               return;
        while ( curfield < result->numfields  ) {
                raw = _row[curfield];
                data = &row->field_values[curfield];
diff --git a/drivers/mysql/dbd_mysql.c b/drivers/mysql/dbd_mysql.c
index a167fdf..94c11f6 100644
--- a/drivers/mysql/dbd_mysql.c
+++ b/drivers/mysql/dbd_mysql.c
@@ -273,13 +273,10 @@ int dbd_free_query(dbi_result_t *result) {
 }
 
 int dbd_goto_row(dbi_result_t *result, unsigned long long rowidx, unsigned 
long long currowidx) {
-  if (rowidx != currowidx+1) {
        mysql_data_seek((MYSQL_RES *)result->result_handle, rowidx);
        /* the return type of this function is indeed void, so it is
           unclear what happens if rowidx is outside the range. The
           calling function must make sure the row index is valid */
-  }
-  /* else: nothing to do, next fetch will fetch next row */
        return 1;
 }
 
@@ -837,6 +834,8 @@ void _get_row_data(dbi_result_t *result, dbi_row_t *row, 
unsigned long long rowi
        dbi_data_t *data;       
 
        _row = mysql_fetch_row(_res);
+       if (_row == NULL)
+               return;
        strsizes = (size_t *)mysql_fetch_lengths(_res);
 
        while (curfield < result->numfields) {
-- 
# Created with git-export-patch

------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.  Get 
unparalleled scalability from the best Selenium testing platform available.
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
_______________________________________________
Libdbi-drivers-devel mailing list
Libdbi-drivers-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libdbi-drivers-devel

Reply via email to