Thread: 32-bit ints on 64-bit linux
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
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;
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
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/
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
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
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/
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