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

Eddy Pronk epronk at muftor.com
Mon Jun 30 18:25:28 EDT 2008


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:
-- 







More information about the FreeTDS mailing list