Обсуждение: 32-bit ints on 64-bit linux

Поиск
Список
Период
Сортировка

32-bit ints on 64-bit linux

От
Kelly Burkhart
Дата:
Greetings,

I am having a problem in running some code in 64 bit unix.  I'm running
unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64.

If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a value
of -1, the insert fails with an 'integer out of range' error.  The
reason this happens is the sprintf near line 2658 of convert.c.

    case SQL_C_SLONG:
    case SQL_C_LONG:
        sprintf(param_string, "%ld",
                *((SDWORD *) buffer));
        break;


How should this be fixed?  Should SQL_C_LONG/SQL_C_SLONG be identified
with the native C long of the compiler?  On Linux/GCC long is 64 bits.
On Windows 64, I believe a long will remain 32 bits.

It seems nicer to me to reserve SQL_C_LONG/SLONG for 32 bit ints and use
SQL_C_SBIGINT/SQL_C_UBIGINT for 64 bit ints.


An alternative approach would be to use:

ipdopts->parameters[param_number].column_size

to select an appropriate sprintf.

What do you ODBC experts consider an appropriate approach.

-K

Re: 32-bit ints on 64-bit linux

От
Kelly Burkhart
Дата:
Replying to my own message...

Kelly Burkhart wrote:
> Greetings,
>
> I am having a problem in running some code in 64 bit unix.  I'm running
> unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64.
>
> If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a value
> of -1, the insert fails with an 'integer out of range' error.  The
> reason this happens is the sprintf near line 2658 of convert.c.
>
>     case SQL_C_SLONG:
>     case SQL_C_LONG:
>         sprintf(param_string, "%ld",
>                 *((SDWORD *) buffer));
>         break;

It appears that SQL_C_LONG does correspond to a 32-bit integer and not
the native long.

I'm attaching a patch which fixes this, and some other questionable
sprintf format strings in convert.c.

-K
--- psqlodbc-08.00.0005/convert.c    2005-01-17 04:12:52.000000000 -0600
+++ psqlodbc-08.00.0005.patch/convert.c    2005-03-03 08:26:38.443591978 -0600
@@ -180,18 +180,31 @@
 #ifdef    WIN32
 #define    ATOI64    _atoi64
 #define    ATOI64U    _atoi64
-#define    FORMATI64    "%I64d"
-#define    FORMATI64U    "%I64u"
 #elif    defined(HAVE_STRTOLL)
 #define    ATOI64(val)    strtoll(val, NULL, 10)
 #define    ATOI64U(val)    strtoull(val, NULL, 10)
-#define    FORMATI64    "%lld"
-#define    FORMATI64U    "%llu"
 #else /* HAVE_STRTOLL */
 #endif /* WIN32 */
 #endif /* ODBCINT64 */

 /*
+ * sprintf formats
+ */
+#define FORMATI8    "%hhd"
+#define FORMATI8U    "%hhu"
+#define FORMATI16    "%hd"
+#define FORMATI16U    "%hu"
+#define FORMATI32    "%d"
+#define FORMATI32U    "%u"
+#ifdef WIN32
+#  define FORMATI64    "%I64d"
+#  define FORMATI64U    "%I64u"
+#else
+#  define FORMATI64    "%lld"
+#  define FORMATI64U    "%llu"
+#endif
+
+/*
  *    TIMESTAMP <-----> SIMPLE_TIME
  *        precision support since 7.2.
  *        time zone support is unavailable(the stuff is unreliable)
@@ -2655,7 +2668,7 @@

         case SQL_C_SLONG:
         case SQL_C_LONG:
-            sprintf(param_string, "%ld",
+            sprintf(param_string, FORMATI32,
                     *((SDWORD *) buffer));
             break;

@@ -2673,28 +2686,28 @@
 #endif /* ODBCINT64 */
         case SQL_C_SSHORT:
         case SQL_C_SHORT:
-            sprintf(param_string, "%d",
+            sprintf(param_string, FORMATI16,
                     *((SWORD *) buffer));
             break;

         case SQL_C_STINYINT:
         case SQL_C_TINYINT:
-            sprintf(param_string, "%d",
+            sprintf(param_string, FORMATI8,
                     *((SCHAR *) buffer));
             break;

         case SQL_C_ULONG:
-            sprintf(param_string, "%lu",
+            sprintf(param_string, FORMATI32U,
                     *((UDWORD *) buffer));
             break;

         case SQL_C_USHORT:
-            sprintf(param_string, "%u",
+            sprintf(param_string, FORMATI16U,
                     *((UWORD *) buffer));
             break;

         case SQL_C_UTINYINT:
-            sprintf(param_string, "%u",
+            sprintf(param_string, FORMATI8U,
                     *((UCHAR *) buffer));
             break;


Re: 32-bit ints on 64-bit linux

От
tomas@nocrew.org (Tomas Skäre)
Дата:
Kelly Burkhart <kelly@kkcsm.net> writes:

> Replying to my own message...
>
> Kelly Burkhart wrote:
> > Greetings,
> > I am having a problem in running some code in 64 bit unix.  I'm
> > running unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64.
> > If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a
> > value of -1, the insert fails with an 'integer out of range' error.
> > The reason this happens is the sprintf near line 2658 of convert.c.
> >     case SQL_C_SLONG:
> >     case SQL_C_LONG:
> >         sprintf(param_string, "%ld",
> >                 *((SDWORD *) buffer));
> >         break;
>
> It appears that SQL_C_LONG does correspond to a 32-bit integer and not
> the native long.
>
> I'm attaching a patch which fixes this, and some other questionable
> sprintf format strings in convert.c.

Just a note on this. There are already standardized format string
defines (when including inttypes.h) for different sizes:

PRId8, PRId16, PRId32, PRId64, PRIu8, PRIu16, PRIu32, PRIu64, ...

It may be better to use those. However, I don't know if they are
available in Windows.


Greetings,

Tomas

Re: 32-bit ints on 64-bit linux

От
Peter Eisentraut
Дата:
Am Donnerstag, 3. März 2005 16:05 schrieb Kelly Burkhart:
> I'm attaching a patch which fixes this, and some other questionable
> sprintf format strings in convert.c.

Do we have any evidence that the other ones are broken?

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

Re: 32-bit ints on 64-bit linux

От
Kelly Burkhart
Дата:
On Fri, 2005-03-18 at 09:25, Peter Eisentraut wrote:
> Am Donnerstag, 3. März 2005 16:05 schrieb Kelly Burkhart:
> > I'm attaching a patch which fixes this, and some other questionable
> > sprintf format strings in convert.c.
>
> Do we have any evidence that the other ones are broken?

No, I do not.

I suggested that the other format strings were questionable based on a
reading of the glibc printf man page.  Aside from the 32-bit integer
problem the other formats work fine in the unmodified form on the three
platforms I use.

Can anyone with a better understanding of the libc standard comment on
the "correctness" of the following lines?

int8_t i1;
int16_t i2;

printf("%d", i1);
printf("%d", i2);

vs:

printf("%hhd", i1);
printf("%hd", i2);

-K

Re: 32-bit ints on 64-bit linux

От
Tom Lane
Дата:
Kelly Burkhart <kelly@tradebotsystems.com> writes:
> Can anyone with a better understanding of the libc standard comment on
> the "correctness" of the following lines?

> int8_t i1;
> int16_t i2;

> printf("%d", i1);
> printf("%d", i2);

That's perfectly correct, unless int is narrower than 16 bits on your
platform ;-).  Anything narrower than int is implicitly coerced to int
when it's passed to printf.  The existence of the h modifier in the
printf format syntax is for scanf, not printf; scanf does have to
know the difference between int and narrower-than-int variables.

            regards, tom lane

Re: 32-bit ints on 64-bit linux

От
Peter Eisentraut
Дата:
Kelly Burkhart wrote:
> I suggested that the other format strings were questionable based on
> a reading of the glibc printf man page.  Aside from the 32-bit
> integer problem the other formats work fine in the unmodified form on
> the three platforms I use.

Given the information provided by Tom Lane, would you submit an updated
patch?  Thanks.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

Re: 32-bit ints on 64-bit linux

От
Kelly Burkhart
Дата:
On Wed, 2005-03-30 at 12:02, Peter Eisentraut wrote:
> Kelly Burkhart wrote:
> > I suggested that the other format strings were questionable based on
> > a reading of the glibc printf man page.  Aside from the 32-bit
> > integer problem the other formats work fine in the unmodified form on
> > the three platforms I use.
>
> Given the information provided by Tom Lane, would you submit an updated
> patch?  Thanks.

Certainly.  Here it is.

-K



Вложения