From: Nathaniel Talbott Date: 2003-11-11T03:55:00+09:00 Subject: Re: Segfault in Ruby/ODBC Nathaniel Talbott [mailto:nathaniel@NOSPAMtalbott.ws] wrote: > I'll dig in to do_fetch and > see if I can find the memory problem. OK, I'm pretty sure I've fixed the problem... for anyone who's interested, I've included a patch with all of my changes to odbc.c. Turns out the problem lay in one of the underlying library functions (SQLColAttributes) claiming to return a zero-length string when the requested value (SQL_COLUMN_TABLE_NAME) didn't exist, but instead not returning anything, leaving the buffer the value was supposed to be put in to in a hosed state. I've fixed it for the time being by making sure the buffer always starts with a NULL value, so that it will always be interpreted as an empty string if the function doesn't do anything to it. I don't know if this will work if the extension is built with unicode support, but since I don't have to deal with that environment, I don't really care at this point. If there's a better solution, I'm all ears. Thanks for all your help, Nathaniel <:((>< --- ../odbc.c.old Thu Aug 21 14:44:37 2003 +++ odbc.c Mon Nov 10 12:51:05 2003 @@ -1021,7 +1021,7 @@ */ static VALUE -env_new(self) +env_new(VALUE self) { ENV *e; SQLHENV henv = SQL_NULL_HENV; @@ -1904,6 +1904,7 @@ char name[SQL_MAX_MESSAGE_LENGTH]; #endif + name[0] = 0; if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, SQLColAttributes(hstmt, ic, SQL_COLUMN_LABEL, name, (SQLSMALLINT) sizeof (name), @@ -1940,6 +1941,7 @@ rb_iv_set(obj, "@name", rb_tainted_str_new2(upcase_if(name, upc))); #endif v = Qnil; + name[0] = 0; if (succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt, SQLColAttributes(hstmt, ic, SQL_COLUMN_TABLE_NAME, name, (SQLSMALLINT) sizeof (name), @@ -3713,6 +3715,7 @@ #endif for (i = 0; i < q->ncols; i++) { + name[0] = 0; if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt, SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1), @@ -3730,6 +3733,7 @@ #else need += 2 * (strlen(name) + 1); #endif + name[0] = 0; if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt, SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1), @@ -3757,6 +3761,7 @@ for (i = 0; i < q->ncols; i++) { char *p0; + name[0] = 0; tracesql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt, SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_TABLE_NAME, name, @@ -3771,6 +3776,7 @@ strcat(p, "."); p += strlen(p); p0 = p; + name[0] = 0; tracesql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt, SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1), SQL_COLUMN_LABEL, name, @@ -5426,8 +5432,11 @@ rb_define_method(Cproc, "initialize", stmt_proc_init, -1); rb_define_method(Cproc, "call", stmt_proc_call, -1); rb_define_method(Cproc, "[]", stmt_proc_call, -1); + +#ifndef HAVE_RB_DEFINE_ALLOC_FUNC rb_enable_super(Cproc, "call"); rb_enable_super(Cproc, "[]"); +#endif /* constants */ for (i = 0; o_const[i].name != NULL; i++) {