I used libdbi with the freetds driver from Linux to connect to a sybase
server on Solaris.
My database had a table with a column which was VARCHAR(20)
One of the rows had exactly 20 characters.
In this case libdbi returns an empty result.
I found 2 problems:
* dbd_freetds.c doesn't allocate enought to store the a null terminator.
* freetds ignores a field when it has exactly 20 characters.
I think I fixed both. I used valgrind to find the memory allocation usage.
diff --git a/drivers/freetds/dbd_freetds.c b/drivers/freetds/dbd_freetds.c
index e7df09a..5b5e13e 100644
--- a/drivers/freetds/dbd_freetds.c
+++ b/drivers/freetds/dbd_freetds.c
@@ -977,8 +977,9 @@ dbi_row_t *_dbd_freetds_buffers_binding(dbi_conn_t *
conn, dbi_result_t * result
/*
* Result is more that 8 bytes -
* allocate additional memory
+ * 1 extra byte for \0
*/
- addr = row->field_values[idx].d_string = (char *)
malloc(row->field_sizes[idx]);
+ addr = row->field_values[idx].d_string = (char *)
malloc(row->field_sizes[idx] + 1);
break;
default:
/* Prepare union to data copy */
--
--------------------
I posted the following to the freetds mailing list:
I used freetds from Linux to connect to a sybase server on Solaris.
My database had a table with a column which was VARCHAR(20)
One of the rows had exactly 20 characters.
With a simple SELECT it hit this piece of code which returns CS_FAIL
without logging anything:
538 case CS_FMT_NULLTERM:
539 if (src_len == destlen) {
540 ret = CS_FAIL; /* not enough room for
data + a null terminator - error */
541 } else {
542 memcpy(dest, srcdata, src_len);
543 dest[src_len] = '\0';
544 if (resultlen != NULL)
545 *resultlen = src_len + 1;
546 ret = CS_SUCCEED;
547 }
548 break;
and the similar:
765 case CS_FMT_NULLTERM:
766 tdsdump_log(TDS_DBG_FUNC, "cs_convert()
FMT_NULLTERM\n");
767 if (len == destlen) {
768 tdsdump_log(TDS_DBG_FUNC, "not enough room for
data + a null terminator - error\n");
769 ret = CS_FAIL; /* not enough room for data +
a null terminator - error */
770 } else {
771 memcpy(dest, cres.c, len);
772 dest[len] = 0;
773 if (resultlen != NULL)
774 *resultlen = len + 1;
775 ret = CS_SUCCEED;
776 }
777 break;
I included a patch below.
I'm not sure if the data structure which holds the length of the field
needs updating.
If I allocate 1 byte extra for the null terminator my query works.
I tried this with Debian testing.
Eddy
diff --git a/src/ctlib/cs.c b/src/ctlib/cs.c
index de6bbda..7fc0595 100644
--- a/src/ctlib/cs.c
+++ b/src/ctlib/cs.c
@@ -389,15 +389,12 @@ CS_RETCODE ret;
switch (destfmt->format) {
case CS_FMT_NULLTERM:
- if (src_len == destlen) {
- ret = CS_FAIL; /* not enough room for data +
a null terminator - error */
- } else {
- memcpy(dest, srcdata, src_len);
- dest[src_len] = '\0';
- if (resultlen != (CS_INT *) NULL)
- *resultlen = src_len + 1;
- ret = CS_SUCCEED;
- }
+ memcpy(dest, srcdata, src_len);
+ /* client code should allocate enough room for data
+ a null terminator */
+ dest[src_len] = '\0';
+ if (resultlen != (CS_INT *) NULL)
+ *resultlen = src_len + 1;
+ ret = CS_SUCCEED;
break;
case CS_FMT_PADBLANK:
@@ -615,16 +612,12 @@ CS_RETCODE ret;
case CS_FMT_NULLTERM:
tdsdump_log(TDS_DBG_FUNC, "cs_convert() FMT_NULLTERM\n");
- if (len == destlen) {
- tdsdump_log(TDS_DBG_FUNC, "not enough room for data
+ a null terminator - error\n");
- ret = CS_FAIL; /* not enough room for data + a
null terminator - error */
- } else {
- memcpy(dest, cres.c, len);
- dest[len] = 0;
- if (resultlen != (CS_INT *) NULL)
- *resultlen = len + 1;
- ret = CS_SUCCEED;
- }
+ /* client code should allocate enough room for data + a
null terminator */
+ memcpy(dest, cres.c, len);
+ dest[len] = '\0';
+ if (resultlen != (CS_INT *) NULL)
+ *resultlen = len + 1;
+ ret = CS_SUCCEED;
break;
case CS_FMT_PADBLANK:
--
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Libdbi-drivers-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libdbi-drivers-devel