Skip to content

Commit

Permalink
fix(c/driver/postgresql): Prevent SQL Injection in GetTableSchema (#657)
Browse files Browse the repository at this point in the history
Fixes #643.
  • Loading branch information
WillAyd authored May 9, 2023
1 parent 5b01ed2 commit e0135af
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
2 changes: 1 addition & 1 deletion c/driver/postgresql/connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ AdbcStatusCode PostgresConnection::GetTableSchema(const char* catalog,
return ADBC_STATUS_INVALID_ARGUMENT;
}

int ret = StringBuilderAppend(&query, "%s%s", table_name, "'::regclass::oid");
int ret = StringBuilderAppend(&query, "%s%s", table, "'::regclass::oid");
PQfreemem(table);

if (ret != 0) return ADBC_STATUS_INTERNAL;
Expand Down
36 changes: 36 additions & 0 deletions c/driver/postgresql/postgresql_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "validation/adbc_validation_util.h"

using adbc_validation::IsOkStatus;
using adbc_validation::IsStatus;

class PostgresQuirks : public adbc_validation::DriverQuirks {
public:
Expand Down Expand Up @@ -97,6 +98,41 @@ class PostgresConnectionTest : public ::testing::Test,
protected:
PostgresQuirks quirks_;
};

TEST_F(PostgresConnectionTest, MetadataGetTableSchemaInjection) {
if (!quirks()->supports_bulk_ingest()) {
GTEST_SKIP();
}
ASSERT_THAT(AdbcConnectionNew(&connection, &error), IsOkStatus(&error));
ASSERT_THAT(AdbcConnectionInit(&connection, &database, &error), IsOkStatus(&error));
ASSERT_THAT(quirks()->DropTable(&connection, "bulk_ingest", &error),
IsOkStatus(&error));
ASSERT_THAT(quirks()->EnsureSampleTable(&connection, "bulk_ingest", &error),
IsOkStatus(&error));

adbc_validation::Handle<ArrowSchema> schema;
ASSERT_THAT(AdbcConnectionGetTableSchema(&connection, /*catalog=*/nullptr,
/*db_schema=*/nullptr,
"0'::int; DROP TABLE bulk_ingest;--",
&schema.value, &error),
IsStatus(ADBC_STATUS_IO, &error));

ASSERT_THAT(
AdbcConnectionGetTableSchema(&connection, /*catalog=*/nullptr,
/*db_schema=*/"0'::int; DROP TABLE bulk_ingest;--",
"DROP TABLE bulk_ingest;", &schema.value, &error),
IsStatus(ADBC_STATUS_IO, &error));

ASSERT_THAT(AdbcConnectionGetTableSchema(&connection, /*catalog=*/nullptr,
/*db_schema=*/nullptr, "bulk_ingest",
&schema.value, &error),
IsOkStatus(&error));

ASSERT_NO_FATAL_FAILURE(adbc_validation::CompareSchema(
&schema.value, {{"int64s", NANOARROW_TYPE_INT64, true},
{"strings", NANOARROW_TYPE_STRING, true}}));
}

ADBCV_TEST_CONNECTION(PostgresConnectionTest)

class PostgresStatementTest : public ::testing::Test,
Expand Down

0 comments on commit e0135af

Please sign in to comment.