freetds AT lists.ibiblio.org
Subject: FreeTDS Development Group
List archive
[freetds] assert in odbc driver for long error messages
- From: Mark Brand <mabrand AT mabrand.nl>
- To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
- Subject: [freetds] assert in odbc driver for long error messages
- Date: Tue, 17 Apr 2012 15:35:23 +0200
Hi,
It seems that a rather long error message raised from a stored procedure triggers an ASSERT in the FreeTDS ODBC driver:
unicode: odbc_util.c:391: odbc_set_string_flag: Assertion `dest == ((void *)0) || dest-(SQLWCHAR*) buffer == out_len' failed.
Aborted
The attached rather primitive code illustrates the problem. The stored procedure is in the comment at the top.
I'm not very familiar with the code in question, but it looks to me that odbc_set_string_flag() is copying more than bytes than the limit imposed by cbBuffer, which is called cbErrorMsgMax from tdsdump_log() in error.c. In my debugger I see that initial_size is 1024 while out_len is 1127 just before the ASSERT.
regards,
Mark
#define UNICODE 1 #define _UNICODE 1 #ifdef WIN32 #include <windows.h> #endif #include <stdio.h> #include <wchar.h> #include <sql.h> #include <sqlext.h> #include <stdlib.h> #include <string.h> /* Demonstration of triggered assert when invoking this stored procedure using FreeTDS odbc driver: create procedure proc_longerror as begin raiserror('reallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylongreallylong error', 16, 1) end */ static void extract_error( char *fn, SQLHANDLE handle, SQLSMALLINT type); SQLTCHAR* toSQLTCHAR(const char *s) { int size = strlen(s) + 1; SQLTCHAR* t = (SQLTCHAR*)malloc(size * sizeof(SQLTCHAR)); int i; for (i = 0; i < size; i++) t[i] = s[i]; return t; } char* fromSQLTCHAR(SQLTCHAR* t, int len) { char *s = (char*)malloc(len +1); int i; for(i = 0; i < len; i++) s[i] = t[i]; s[len] = '\0'; return s; } main() { SQLHENV env; SQLHDBC dbc; SQLHSTMT stmt; SQLRETURN ret; /* ODBC API return status */ SQLTCHAR outstr[1024]; SQLSMALLINT outstrlen = 0; /* Allocate an environment handle */ SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); /* We want ODBC 3 support */ SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); /* Allocate a connection handle */ SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); printf("SQLTCHAR size is: %d\n", sizeof(SQLTCHAR)); /* Connect to the DSN mydsn */ const char *cn = "DSN=dsn;UID=user;PWD=password;"; SQLTCHAR *tcn = toSQLTCHAR(cn); memset(outstr, 0, 1024 * sizeof(SQLTCHAR)); ret = SQLDriverConnect(dbc, NULL, tcn, strlen(cn) * sizeof(SQLTCHAR), outstr, 1024, &outstrlen, 0); if (SQL_SUCCEEDED(ret)) { printf("Connected\n"); printf("Returned connection string was:\n\t%s\n", fromSQLTCHAR(outstr, outstrlen)); if (ret == SQL_SUCCESS_WITH_INFO) { printf("Driver reported the following diagnostics\n"); extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC); } } else { fprintf(stderr, "Failed to connect\n"); extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC); } SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); const char *cmd = "{CALL proc_longerror}"; SQLTCHAR* tcmd = toSQLTCHAR(cmd); ret = SQLExecDirect(stmt, tcmd, SQL_NTS); if (SQL_SUCCEEDED(ret)) { printf("Success\n"); if (ret == SQL_SUCCESS_WITH_INFO) { printf("Driver reported the following diagnostics\n"); extract_error("SQLExecDirect", stmt, SQL_HANDLE_STMT); } } else { fprintf(stderr, "SQLExecDirect Failed\n"); extract_error("SQLExecDirect", stmt, SQL_HANDLE_STMT); } SQLFreeHandle(SQL_HANDLE_DBC, stmt); SQLDisconnect(dbc); /* free up allocated handles */ SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); } void extract_error( char *fn, SQLHANDLE handle, SQLSMALLINT type) { SQLINTEGER i = 0; SQLINTEGER native; SQLWCHAR state[ 7 ]; SQLWCHAR text[256]; SQLSMALLINT len; SQLRETURN ret; fprintf(stderr, "\n" "The driver reported the following diagnostics whilst running " "%s\n\n", fn); do { ret = SQLGetDiagRec(type, handle, ++i, state, &native, text, 256, &len ); if (SQL_SUCCEEDED(ret)) printf("%ls:%ld:%ld:%s\n", state, i, native, fromSQLTCHAR(text, len)); } while( ret == SQL_SUCCESS ); }
-
[freetds] assert in odbc driver for long error messages,
Mark Brand, 04/17/2012
-
Re: [freetds] assert in odbc driver for long error messages,
Frediano Ziglio, 04/20/2012
- Re: [freetds] assert in odbc driver for long error messages, Frediano Ziglio, 04/21/2012
-
Re: [freetds] assert in odbc driver for long error messages,
Frediano Ziglio, 04/20/2012
Archive powered by MHonArc 2.6.24.