Changeset: 55b7f9555245 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/55b7f9555245
Modified Files:
        clients/odbc/tests/odbcconnect.c
        sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Test non-NUL-terminated arguments


diffs (172 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -17,6 +17,7 @@
 #endif
 
 #include <assert.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -33,6 +34,7 @@ static const char *USAGE =
        "        -l              List registered drivers and data sources\n"
        "        -u USER\n"
        "        -p PASSWORD\n"
+       "        -0              use counted strings rather than nul-terminated 
arguments\n"
        "        -v              Be verbose\n"
        "        TARGET          DSN or with -d and -b, Connection String\n";
 
@@ -49,10 +51,16 @@ static int do_listdsns(const char *prefi
 
 static void ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret);
 
+#define MARGIN 100
+static SQLCHAR* sqldup_with_margin(const char *str);
+static void fuzz_sql_nts(SQLCHAR **str, SQLSMALLINT *len);
 
 int verbose = 0;
 SQLCHAR *user = NULL;
+SQLSMALLINT user_len = SQL_NTS;
 SQLCHAR *password = NULL;
+SQLSMALLINT password_len = SQL_NTS;
+bool use_counted_strings = false;
 
 SQLHANDLE env = NULL;
 SQLHANDLE conn = NULL;
@@ -89,13 +97,15 @@ main(int argc, char **argv)
                else if (strcmp(arg, "-l") == 0)
                        action = NULL;
                else if (strcmp(arg, "-u") == 0 && i + 1 < argc)
-                       user = (SQLCHAR*)argv[++i];
+                       user = sqldup_with_margin(argv[++i]);
                else if (strcmp(arg, "-p") == 0 && i + 1 < argc)
-                       password = (SQLCHAR*)argv[++i];
+                       password = sqldup_with_margin(argv[++i]);
+               else if (strcmp(arg, "-0") == 0)
+                       use_counted_strings = true;
                else if (strcmp(arg, "-v") == 0)
                        verbose += 1;
                else if (arg[0] != '-')
-                       targets[ntargets++] = (SQLCHAR*)arg;
+                       targets[ntargets++] = sqldup_with_margin(arg);
                else {
                        fprintf(stderr, "\nERROR: invalid argument: %s\n%s", 
arg, USAGE);
                        ret = 1;
@@ -111,6 +121,11 @@ main(int argc, char **argv)
                SQL_HANDLE_ENV, env, "set odbc version",
                SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, 
(SQLPOINTER)SQL_OV_ODBC3, 0));
 
+       if (use_counted_strings) {
+               fuzz_sql_nts(&user, &user_len);
+               fuzz_sql_nts(&password, &password_len);
+       }
+
        if (action) {
                if (ntargets == 0) {
                        fprintf(stderr, "\nERROR: pass at least one 
target\n%s", USAGE);
@@ -130,6 +145,10 @@ main(int argc, char **argv)
        }
 
 end:
+       free(user);
+       free(password);
+       for (int i = 0; i < ntargets; i++)
+               free(targets[i]);
        free(targets);
        cleanup();
 
@@ -207,9 +226,13 @@ do_actions(action_t action, int ntargets
 static int
 do_sqlconnect(SQLCHAR *target)
 {
+       SQLSMALLINT target_len = SQL_NTS;
+       if (use_counted_strings)
+               fuzz_sql_nts(&target, &target_len);
+
        ensure_ok(
                SQL_HANDLE_DBC, conn, "SQLConnect",
-               SQLConnect(conn, target, SQL_NTS, user, SQL_NTS, password, 
SQL_NTS));
+               SQLConnect(conn, target, target_len, user, user_len, password, 
password_len));
        printf("OK\n");
 
        return 0;
@@ -219,11 +242,15 @@ static int
 do_sqldriverconnect(SQLCHAR *target)
 {
        SQLSMALLINT n;
+       SQLSMALLINT target_len = SQL_NTS;
+       if (use_counted_strings)
+               fuzz_sql_nts(&target, &target_len);
+
        ensure_ok(
                SQL_HANDLE_DBC, conn, "SQLDriverConnect",
                SQLDriverConnect(
                        conn, NULL,
-                       target, SQL_NTS,
+                       target, target_len,
                        outbuf, sizeof(outbuf), &n,
                        SQL_DRIVER_NOPROMPT
                ));
@@ -236,9 +263,13 @@ static int
 do_sqlbrowseconnect(SQLCHAR *target)
 {
        SQLSMALLINT n;
+       SQLSMALLINT target_len = SQL_NTS;
+       if (use_counted_strings)
+               fuzz_sql_nts(&target, &target_len);
+
        SQLRETURN ret = SQLBrowseConnect(
                conn,
-               target, SQL_NTS,
+               target, target_len,
                outbuf, sizeof(outbuf), &n
        );
        ensure_ok(SQL_HANDLE_DBC, conn, "SQLBrowseConnect", ret);
@@ -302,3 +333,27 @@ do_listdsns(const char *prefix, SQLSMALL
        return 0;
 }
 
+
+static SQLCHAR*
+sqldup_with_margin(const char *str)
+{
+       size_t len = strlen(str);
+       char *buf = malloc(len + MARGIN);
+       memmove(buf, str, len);
+       memset(buf + len, 0, MARGIN);
+       return (SQLCHAR*)buf;
+}
+
+static void
+fuzz_sql_nts(SQLCHAR **str, SQLSMALLINT *len)
+{
+       if (*str != NULL) {
+               // append garbage so it's no longer properly NUL terminated,
+               // indicate original length through 'len'
+               size_t n = strlen((char*)*str);
+               const char *garbage = "GARBAGE";
+               size_t garblen = strlen(garbage);
+               memmove(*str + n, garbage, garblen + 1); // include the 
trailing NUL
+               *len = (SQLSMALLINT)n;
+       }
+}
diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -134,4 +134,15 @@ ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
 ex.end()
 
+# test non-NUL terminated strings
+
+ex = Execution(dbname, '-0')
+ex.expect('OK')
+ex.end()
+
+ex = Execution(dbname, '-0', '-u', 'monetdb', '-p', 'monetdb')
+ex.expect('OK')
+ex.end()
+
+
 ex = None
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to