[freetds] [PATCH] Problem with VARCHAR in sybase.

Eddy Pronk epronk at muftor.com
Tue Jul 1 00:32:29 EDT 2008

> Eddy Pronk wrote:
>> 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:
> ...
>> I included a patch below.
> ...
>> If I allocate 1 byte extra for the null terminator my query works.
> Thank you for the patch.  You've highlighted a problem, but I don't think
> your fix is the right one.
> In the first place, ct-lib needs some time and attention paid to error
> messages.  There are many places where it works if used correctly but
> fails silently (except for the return code) if not.  We need a function
> similar to dbperror().
> Second, afaict CS_FMT_NULLTERM is invalid in cs_convert (cf.
> http://manuals.sybase.com:80/onlinebooks/group-oc/ocg1250e/occpr/@ebt-link;pt=2420?target=%25N%14_2686_START_RESTART_N%25).
> Third, even if valid, istm the code is basically right: if the destination
> buffer does not have room for a NULL terminator and the format
> specification for the conversion demands one, the conversion should fail.

I'll look at the code again tonight.
The context in which I found this problem was by using libdbi which has a
driver to talk to freetds.

I fixed it this way because I think destlen is setup by freetds.
Maybe the way libdbi uses the API needs attention.


---------------------------- Original Message ----------------------------
Subject: [PATCH] Problem with VARCHAR in freetds (sybase)
From:    "Eddy Pronk" <epronk at muftor.com>
Date:    Sun, June 29, 2008 10:25 am
To:      libdbi-drivers-devel at lists.sourceforge.net

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 *)
+        addr = row->field_values[idx].d_string = (char *)
malloc(row->field_sizes[idx] + 1);
         /* Prepare union to data copy */

More information about the FreeTDS mailing list