Re: INFORMIX ESQL/C prepare statement crashes
Posted in 1997
I think your "stmt_buf[40]" is too short to accomodate to the request buffer, once it is merged with your table name (here it crashes on some stack variables if your table name is more than 12 characters long). So if you use this function to find whever a key name is a column name of a given table of your informix schema, you'll get into trouble with some tables. Note : the fixed part of your request in the sprintf() call is 23 characters, then %s should accomodate with a valid table name (up to 18 characters with IFX), then you need an extra space for the ending NUL byte, so your buffer should be at least 23+18+1=42 bytes long. Change the declaration from 40 to 64 and you'll solve your problem. This is a classic bug of some C programmers due to incorrect use of the dangerous sprintf() function of C. If you don't fix correct bounds to buffers, sprintf() may overwrite the buffer limits and crash your application (here, as the buffer is declared locally, it may overwrite other local variables or the call stack, but you won't notice the crash until one of these (unexpected) overwritten local variables are further accessed, or until your function returns to its caller. C is not C++, and the C function sprintf() cannot control the size of the buffer you give in argument. Some Unix and NT have an extra snprintf() call which allow you to specify the maximum buffer size in addition to the buffer address, and it returns the actual count of bytes written. If the returned value equals the buffer size, then you know that your buffer is too small. With C++, you should have used a "string" or "TString" instance with overloaded << operators, without worrying about buffer size because such a class imlements an automatic memory (re)allocation scheme. In addition, the ANSI standard for printf-like function limits each variable field to no more than 508 characters (it is actually 512 on most DOS/Windows C compiler products, and often 1024 under Unix), because of a required limit of their internal field formatter which requires a local storage buffer for field formatting. Some implementations of printf-like functions do not use internal buffering and don't have such a limit. So the use of sprintf() is dangerous also when you use it multiple times (may be with conditional parts) to create a large request, because this often involves using %s many times, and for the last calls, one of your %s fields may be longer than this ANSI-C limit. The only advantage of using sprintf() is that it is simple to write and use, but it is not without troubles. However, sprintf() is a complex function, with no type-checking for its arguments (suppose you have many %s and %d or %ld fields in your format string, and suppose you change the datatype of only one of the next arguments, or just remove or add one: no check can be done at compile-time or run-time to see the actual datatype of your arguments (unless you use a GNU-C compiler which accepts special pragmas for printf() and scanf() like functions declarations, allowing compile-time warnings for field arguments which are not compatible with the %XXX specifiers found in a leading "constant format-string"). So take the time to re-read your C documentation. lea@fairfax-emh1.army.mil a 'crit dans le message <881601751.9760@dejanews.com>... >Hello All, > >I am having a problem with a prepare statement crashes after several >calls. See below for more detail. > >We are using INFORMIX Online Server 7.10.UC2, INFORMIX-ESQL Version >5.02.UC7 on HP-UX 9.03 and encountering problem on the following function >written in ESQL/C: > >int KeyFound (table_name, key_name) >char *table_name; >char *key_name; >{ > struct sqlda *descp; > $char stmt_buf[40]; > int i, found; > > sprintf (stmt_buf, "select * from informix.%s", table_name); > > $prepare select_stmt from :stmt_buf; > if (SQLCODE != 0) > return SQLCODE; > > $describe select_stmt into descp; > if (SQLCODE != 0) > return SQLCODE; > > found = 0; > > for (i = 0; !found && i < descp->sqld; i++) > { > if (strcmp (descp->sqlvar[i].sqlname, key_name) == 0) > found = 1; > } > > $free select_stmt; > free (descp); > > return found; >} > >The calling program executes this function multiple times. On the Nth >call, when the prepare statement executes, the program crahes and exits >to the UNIX prompt with no error message. > >-------------------==== Posted via Deja News ====----------------------- > http://www.dejanews.com/ Search, Read, Post to Usenet