Skip to content

Commit

Permalink
ODBC-343 an attempt to add DSN in odbc admin caused crash
Browse files Browse the repository at this point in the history
The dialog called TestDSN at wrong time/conditions.
Commit also fixes interactive and dsn_test tests and adjusts the ctest timeout for
it.
  • Loading branch information
lawrinn committed Nov 9, 2021
1 parent 80ac5f2 commit 24c7554
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 27 deletions.
35 changes: 23 additions & 12 deletions dsn/odbc_dsn.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ my_bool SetDialogFields()
int i= 0;
MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);

/* Basically - if dialog does not exist yet */
if (Dsn == NULL)
{
return TRUE;
}
while (DsnMap[i].Key)
{
switch (DsnMap[i].Key->Type) {
Expand Down Expand Up @@ -492,7 +497,8 @@ static SQLRETURN TestDSN(MADB_Dsn *Dsn, SQLHANDLE *Conn, SQLCHAR *ConnStrBuffer)
}

DsnApplyDefaults(Dsn);
/* If defaults has changed actual values - let them be reflected in the dialog */
/* If defaults has changed actual values - let them be reflected in the dialog(if it exists - SetDialogFields
cares about that) */
SetDialogFields();
MADB_DsnToString(Dsn, ConnStr, CONNSTR_BUFFER_SIZE);

Expand Down Expand Up @@ -852,10 +858,10 @@ void CenterWindow(HWND hwndWindow)


BOOL DSNDialog(HWND hwndParent,
WORD fRequest,
LPCSTR lpszDriver,
LPCSTR lpszAttributes,
MADB_Dsn *Dsn)
WORD fRequest,
LPCSTR lpszDriver,
LPCSTR lpszAttributes,
MADB_Dsn *Dsn)
{
MSG msg;
BOOL ret;
Expand Down Expand Up @@ -927,13 +933,18 @@ BOOL DSNDialog(HWND hwndParent,
Dsn->Driver= _strdup(lpszDriver);
}

if (SQL_SUCCEEDED(TestDSN(Dsn, NULL, NULL)))
{
return MADB_SaveDSN(Dsn);
}
else if (hwndParent == NULL)
/* If we don't have parent window - we are not supposed to show the dialog, but only
perform operation, if sufficient data has been provided */
if (hwndParent == NULL)
{
return FALSE;
if (SQL_SUCCEEDED(TestDSN(Dsn, NULL, NULL)))
{
return MADB_SaveDSN(Dsn);
}
else
{
return FALSE;
}
}

break;
Expand Down Expand Up @@ -963,7 +974,7 @@ BOOL DSNDialog(HWND hwndParent,
{
return MADB_SaveDSN(Dsn);
}
else if (hwndParent == NULL)
else
{
return FALSE;
}
Expand Down
31 changes: 21 additions & 10 deletions dsn_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <odbcinst.h>

typedef BOOL (*DSNDialog)(HWND hwndParent,
Expand All @@ -33,7 +34,17 @@ int main()
DSNDialog DsnFunc= NULL;
HWND hWnd;
DWORD dwProcID= GetCurrentProcessId();
const char *driver= getenv("TEST_DRIVER");

if (driver == NULL)
{
printf("Test requires environment variable TEST_DRIVER to be set!\n");
return 1;
}
else
{
printf("# Using Driver=%s for testing.\n", driver);
}
hWnd= GetConsoleWindow();
if (hWnd == NULL)
{
Expand All @@ -52,30 +63,30 @@ int main()
{
if (DsnFunc= (DSNDialog)GetProcAddress(hmod, "ConfigDSN"))
{
ret= DsnFunc(NULL, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
ret= DsnFunc(NULL, ODBC_ADD_DSN, driver, "DSN=dsn_test\0OPTIONS=2\0\0");
printf("%s 1 Null hWnd and not enough info\n", ret ? "not ok" : "ok");

printf("# The dialog is supposed to show up now - please complete info for connection\n");
ret= DsnFunc(hWnd, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
ret= DsnFunc(hWnd, ODBC_ADD_DSN, driver, "DSN=dsn_test\0OPTIONS=2\0\0");

if (ret != FALSE)
{
printf("ok 2 hWnd and not enough info\n");
ret= DsnFunc(NULL, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
ret= DsnFunc(NULL, ODBC_ADD_DSN, driver, "DSN=dsn_test\0OPTIONS=2\0\0");
printf("%s 3 Null hWnd trying to add existing dsn \n", ret ? "not ok" : "ok");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, driver, "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
printf("%s 4 Null hWnd trying to config with insufficient data \n", ret ? "not ok" : "ok");
printf("# The dialog asking if you want to overwrite existing DSN is supposed to show up. Please say 'No'. Otherwise please cancel config dialog\n");
ret= DsnFunc(hWnd, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
ret= DsnFunc(hWnd, ODBC_ADD_DSN, driver, "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
printf("%s 5 Replace Prompt \n", ret ? "not ok" : "ok");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, driver, "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
printf("%s 6 Null hWnd trying to config inexisting DSN\n", ret ? "not ok" : "ok");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, driver, "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
printf("%s 7 hWnd trying to config inexisting DSN\n", ret ? "not ok" : "ok");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=0\0\0");
ret= DsnFunc(NULL, ODBC_CONFIG_DSN, driver, "DSN=dsn_test\0OPTIONS=0\0\0");
printf("%s 8 Null hWnd config with sufficient data \n", ret ? "ok" : "not ok");
printf("# Please make sure that in dialog Named pipe is selected, and all options are un-checked\n");
ret= DsnFunc(hWnd, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0NamedPipe=1\0\0");
ret= DsnFunc(hWnd, ODBC_CONFIG_DSN, driver, "DSN=dsn_test\0NamedPipe=1\0\0");
printf("%s 9 hWnd config with sufficient data \n", ret ? "ok" : "not ok");
}
else
Expand All @@ -96,5 +107,5 @@ int main()
FreeLibrary(hmod);
}

return 1;
return 0;
}
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ FOREACH (ODBC_TEST ${ODBC_TESTS})
ENDIF()
IF (NOT ${ODBC_TEST} STREQUAL "interactive" OR USE_INTERACTIVE_TESTS)
ADD_TEST(odbc_${ODBC_TEST} ${EXECUTABLE_OUTPUT_PATH}/odbc_${ODBC_TEST})
SET_TESTS_PROPERTIES(odbc_${ODBC_TEST} PROPERTIES TIMEOUT 120)
SET_TESTS_PROPERTIES(odbc_${ODBC_TEST} PROPERTIES TIMEOUT 600)
ENDIF()
ENDFOREACH()

Expand Down
60 changes: 56 additions & 4 deletions test/interactive.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.
2016 MariaDB Corporation AB
2016, 2021 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 All @@ -27,6 +27,57 @@

HWND hWnd;

/* {{{ ltrim
copied from ma_common.c
*/
char* ltrim(char* Str)
{
/* I am not sure using iswspace, and not isspace makes any sense here. But probably does not hurt either */
while (Str && iswspace(Str[0]))
++Str;
return Str;
}
/* }}} */
/* Connstr has to be null-terminated - copied from config dialog(odbc_dsn) */
char* HidePwd(char* ConnStr)
{
char* Ptr = ConnStr;

while (*Ptr)
{
BOOL IsPwd = FALSE;
char* KeyValBorder = strchr(Ptr, '=');
char StopChr = ';';

Ptr = ltrim(Ptr);

if (_strnicmp(Ptr, "PWD", 3) == 0 || _strnicmp(Ptr, "PASSWORD", 8) == 0)
{
IsPwd = TRUE;
}
if (KeyValBorder != NULL)
{
Ptr = ltrim(KeyValBorder + 1);
}
if (*Ptr == '{')
{
StopChr = '}';
}
while (*Ptr && *Ptr != StopChr)
{
if (IsPwd)
{
*Ptr = '*';
}
++Ptr;
}
++Ptr;
}

return ConnStr;
}


/* Test of NO_PROMPT option. Normally it is not interactive. Dialog appearance means test failure */
ODBC_TEST(ti_bug30840)
{
Expand All @@ -40,6 +91,7 @@ ODBC_TEST(ti_bug30840)
CHECK_ENV_RC(Env, SQLAllocHandle(SQL_HANDLE_DBC, Env, &hdbc1));

/* NO_PROMPT is supposed to supress dialog invocation, and connect should fail */
diag("You are supposed *not* to see config dialog in this test.");
EXPECT_DBC(hdbc1, SQLDriverConnect(hdbc1, NULL, conn, (SQLSMALLINT)strlen(conn),
conn_out, (SQLSMALLINT)sizeof(conn_out), &conn_out_len,
SQL_DRIVER_COMPLETE_REQUIRED), SQL_ERROR);
Expand All @@ -59,7 +111,7 @@ ODBC_TEST(ti_dialogs)
SQLCHAR conna[512], conna_out[1024];

/* Testing how driver's doing if no out string given. ODBC-17 */
sprintf((char*)conna, "DRIVER=%s;TCPIP=1;SERVER=%s%s", my_drivername, my_servername, ma_strport);
sprintf((char*)conna, "DRIVER=%s;TCPIP=1;SERVER=%s;%s", my_drivername, my_servername, ma_strport);
CHECK_ENV_RC(Env, SQLAllocHandle(SQL_HANDLE_DBC, Env, &hdbc1));

CHECK_DBC_RC(hdbc1, SQLDriverConnect(hdbc1, hWnd, conna, SQL_NTS, NULL,
Expand All @@ -72,7 +124,7 @@ ODBC_TEST(ti_dialogs)
CHECK_DBC_RC(hdbc1, SQLDriverConnect(hdbc1, hWnd, conna, SQL_NTS, conna_out,
sizeof(conna_out), &conn_out_len, SQL_DRIVER_PROMPT));

diag("In %d OutString %s(%d)", strlen(conna), hide_pwd(conna_out), conn_out_len);
diag("In %d OutString %s(%d)", strlen(conna), HidePwd(conna_out), conn_out_len);
/* We can't say much about the out string length, but it supposed to be bigger, than of the in string */
FAIL_IF((size_t)conn_out_len <= strlen(conna), "OutString length is too short");

Expand All @@ -81,7 +133,7 @@ ODBC_TEST(ti_dialogs)
CHECK_DBC_RC(hdbc1, SQLDriverConnect(hdbc1, hWnd, conna, SQL_NTS, conna_out,
sizeof(conna_out), &conn_out_len, SQL_DRIVER_COMPLETE));

diag("In %d OutString %s(%d)", strlen(conna), hide_pwd(conna_out), conn_out_len);
diag("In %d OutString %s(%d)", strlen(conna), HidePwd(conna_out), conn_out_len);
FAIL_IF((size_t)conn_out_len <= strlen(conna), "OutString length is too short");

CHECK_DBC_RC(hdbc1, SQLDisconnect(hdbc1));
Expand Down

0 comments on commit 24c7554

Please sign in to comment.