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