Skip to content

Commit

Permalink
[ODBC-94] The driver would crash with ODBCv2 with exotic exotic
Browse files Browse the repository at this point in the history
sqlstate, e.g. OP000, as a result of bad GRANT syntax.
The reason was that that sqlstate fields in MADB_ERROR struct are
arrays, but connector waited for NULL sqlstate to stop traversing the
MADB_ErrorList array.
Testcase has been added.
Patch also adds convenience function for tests to check if the server meets some minimum version criteria.
We seemingly had problem SQL_DBMS_VER info type. The patch fixes as well.
  • Loading branch information
lawrinn committed May 3, 2017
1 parent 45a1418 commit daaf929
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 24 deletions.
5 changes: 2 additions & 3 deletions ma_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,14 +1057,13 @@ SQLRETURN MADB_DbcGetInfo(MADB_Dbc *Dbc, SQLUSMALLINT InfoType, SQLPOINTER InfoV
break;
case SQL_DBMS_VER:
{
char Version[11];
char Version[13];
ulong ServerVersion= 0L;
unsigned int Major=0, Minor=0, Patch= 0;

if (Dbc->mariadb)
{
ServerVersion= mysql_get_server_version(Dbc->mariadb);
my_snprintf(Version, 11, "%02u.%02u.%06u", ServerVersion / 10000,
_snprintf(Version, sizeof(Version), "%02u.%02u.%06u", ServerVersion / 10000,
(ServerVersion % 10000) / 100, ServerVersion % 100);
}
else
Expand Down
6 changes: 3 additions & 3 deletions ma_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,16 @@ SQLRETURN MADB_GetDiagRec(MADB_Error *Err, SQLSMALLINT RecNumber,
/* check if we have to map the SQLState to ODBC version 2 state */
if (OdbcVersion == SQL_OV_ODBC2)
{
int i=0;
while (MADB_ErrorList[i].SqlState)
int i= 0;
while (MADB_ErrorList[i].SqlState[0])
{
if (strcmp(Err->SqlState, MADB_ErrorList[i].SqlState) == 0)
{
if (MADB_ErrorList[i].SqlStateV2[0])
SqlStateVersion= MADB_ErrorList[i].SqlStateV2;
break;
}
i++;
++i;
}
}

Expand Down
11 changes: 0 additions & 11 deletions ma_result.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,8 @@ SQLRETURN MADB_StmtDataSeek(MADB_Stmt *Stmt, my_ulonglong FetchOffset)
{
return SQL_NO_DATA_FOUND;
}
/*
Stmt->Cursor.Position= 0;
for (tmp= Stmt->stmt->result.data; FetchOffset-- && tmp ; tmp = tmp->next)
Stmt->Cursor.Position++;
Stmt->stmt->result_cursor= tmp;
*/
mysql_stmt_data_seek(Stmt->stmt, FetchOffset);

/* We need to fetch lengths, so SQLGetData will return correct results.
Since we need to prevent overwriting bound variables we will set buffer_types
to SQL_TYPE_NULL temporarily
*/

return SQL_SUCCESS;
}
/* }}} */
Expand Down
31 changes: 30 additions & 1 deletion test/error.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
2013 MontyProgram AB
2013, 2017 MariaDB Corporation AB
The MySQL Connector/ODBC is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
Expand Down Expand Up @@ -594,7 +594,35 @@ ODBC_TEST(t_bug49466)
}


ODBC_TEST(t_odbc94)
{
SQLHANDLE henv1;
SQLHANDLE Connection1;
SQLHANDLE Stmt1;
SQLCHAR conn[512];
SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
SQLINTEGER error;
SQLSMALLINT len;

sprintf((char *)conn, "DRIVER=%s;SERVER=%s;UID=%s;PASSWORD=%s;DATABASE=%s%s;",
my_drivername, my_servername, my_uid, my_pwd, my_schema, ma_strport);

CHECK_ENV_RC(henv1, SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv1));
CHECK_ENV_RC(henv1, SQLSetEnvAttr(henv1, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC2, SQL_IS_INTEGER));
CHECK_ENV_RC(henv1, SQLAllocHandle(SQL_HANDLE_DBC, henv1, &Connection1));
CHECK_DBC_RC(Connection1, SQLDriverConnect(Connection1, NULL, conn, (SQLSMALLINT)strlen(conn), NULL, 0,
NULL, SQL_DRIVER_NOPROMPT));
CHECK_DBC_RC(Connection1, SQLAllocHandle(SQL_HANDLE_STMT, Connection1, &Stmt1));

EXPECT_STMT(Stmt1, SQLExecDirect(Stmt1, "GRANT ALL PRIVILEGES on odbc94 to public", SQL_NTS), SQL_ERROR);

CHECK_STMT_RC(Stmt, SQLGetDiagRec(SQL_HANDLE_STMT, Stmt1, 1, sqlstate, &error,
message, sizeof(message), &len));

return OK;
}


MA_ODBC_TESTS my_tests[]=
Expand All @@ -615,6 +643,7 @@ MA_ODBC_TESTS my_tests[]=
{t_bug13542600, "t_bug13542600"},
{t_bug14285620, "t_bug14285620"},
{t_bug49466, "t_bug49466"},
{t_odbc94, "t_odbc94"},
{NULL, NULL}
};

Expand Down
24 changes: 18 additions & 6 deletions test/result2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,12 +1054,13 @@ ODBC_TEST(t_odbc77)
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

#ifdef MDEV_11966_FIXED
OK_SIMPLE_STMT(Stmt, "ANALYZE SELECT 1");
CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));
#endif
if (ServerNewerThan(Connection, 10, 2, 5))
{
OK_SIMPLE_STMT(Stmt, "ANALYZE SELECT 1");
CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));
}
OK_SIMPLE_STMT(Stmt, "EXPLAIN SELECT 1");
CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
Expand All @@ -1072,6 +1073,17 @@ ODBC_TEST(t_odbc77)
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));*/

/* Just to test some more exotic commands */
OK_SIMPLE_STMT(Stmt, "DROP TABLE IF EXISTS odbc77");
OK_SIMPLE_STMT(Stmt, "CREATE TABLE odbc77(id INT NOT NULL)");
OK_SIMPLE_STMT(Stmt, "TRUNCATE TABLE odbc77");
OK_SIMPLE_STMT(Stmt, "DROP TABLE odbc77");

OK_SIMPLE_STMT(Stmt, "SELECT 1");
CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

return OK;
}

Expand Down
17 changes: 17 additions & 0 deletions test/tap.h
Original file line number Diff line number Diff line change
Expand Up @@ -1116,4 +1116,21 @@ char* hide_pwd(char *connstr)
return connstr;
}


BOOL ServerNewerThan(SQLHDBC Conn, unsigned int major, unsigned int minor, unsigned int patch)
{
unsigned int ServerMajor= 0, ServerMinor= 0, ServerPatch= 0;
SQLCHAR ServerVersion[32];

SQLGetInfo(Conn, SQL_DBMS_VER, ServerVersion, sizeof(ServerVersion), NULL);

sscanf(ServerVersion, "%u.%u.%u", &ServerMajor, &ServerMinor, &ServerPatch);

if (ServerMajor < major || ServerMajor == major && (ServerMinor < minor || ServerMinor == minor && ServerPatch < patch))
{
return FALSE;
}

return TRUE;
}
#endif /* #ifndef _tap_h_ */

0 comments on commit daaf929

Please sign in to comment.