-
Notifications
You must be signed in to change notification settings - Fork 26
FIX: Validate access tokens to prevent crashes #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -219,4 +219,179 @@ def test_error_handling(): | |||||
|
|
||||||
| # Test non-string input | ||||||
| with pytest.raises(ValueError, match="Connection string must be a string"): | ||||||
| process_connection_string(None) | ||||||
| process_connection_string(None) | ||||||
|
|
||||||
|
|
||||||
| def test_short_access_token_protection_blocks_short_tokens(): | ||||||
| """ | ||||||
| Test protection against ODBC driver crashes with malformed access tokens. | ||||||
|
|
||||||
| Microsoft ODBC Driver 18 has a bug where it crashes (segfault on macOS/Linux, | ||||||
| access violation on Windows) when given malformed access tokens. This test | ||||||
| verifies that our defensive validation properly rejects invalid tokens before | ||||||
| they reach the ODBC driver. | ||||||
|
|
||||||
| The validation is implemented in Connection::setAttribute() in connection.cpp | ||||||
| and checks: | ||||||
| 1. Minimum size (4 bytes for ACCESSTOKEN header) | ||||||
| 2. Structure integrity (declared size matches actual size) | ||||||
| 3. Non-empty data (not all zeros) | ||||||
|
|
||||||
| This test runs in a subprocess to isolate potential crashes. | ||||||
| """ | ||||||
| import os | ||||||
| import subprocess | ||||||
|
|
||||||
| # Get connection string and remove UID/Pwd to force token-only mode | ||||||
| conn_str = os.getenv("DB_CONNECTION_STRING") | ||||||
| if not conn_str: | ||||||
| pytest.skip("DB_CONNECTION_STRING environment variable not set") | ||||||
|
|
||||||
| # Remove authentication to force pure token mode | ||||||
| conn_str_no_auth = conn_str | ||||||
| for remove_param in ["UID=", "Pwd=", "uid=", "pwd="]: | ||||||
| if remove_param in conn_str_no_auth: | ||||||
| parts = conn_str_no_auth.split(";") | ||||||
| parts = [p for p in parts if not p.lower().startswith(remove_param.lower())] | ||||||
| conn_str_no_auth = ";".join(parts) | ||||||
|
|
||||||
| # Escape connection string for embedding in subprocess code | ||||||
| escaped_conn_str = conn_str_no_auth.replace('\\', '\\\\').replace('"', '\\"') | ||||||
|
|
||||||
| # Test cases for problematic tokens | ||||||
| test_cases = [ | ||||||
| (b"", "empty token"), | ||||||
| (b"x" * 3, "too small (< 4 bytes)"), | ||||||
| (b"\x00\x00\x00\x00", "header only, no data"), | ||||||
| (b"\x10\x00\x00\x00" + b"\x00" * 16, "size mismatch (declares 16, total 20)"), | ||||||
|
||||||
| (b"\x10\x00\x00\x00" + b"\x00" * 16, "size mismatch (declares 16, total 20)"), | |
| (b"\x08\x00\x00\x00" + b"\x00" * 16, "size mismatch (declares 8, total 20)"), |
Copilot
AI
Oct 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sys is used but never imported in this test function, which will raise a NameError before the subprocess runs. Add import sys near the other imports at the start of the function.
Copilot
AI
Oct 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sys is referenced here but not imported in this function, causing a NameError. Add import sys alongside the other local imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct is used but not imported in this module, which will raise a NameError when this function is called. Add import struct at the top of the file.