pyodbc: Segmentation fault when connecting to SQL Server with an access token

Environment

  • Python: 3.8
  • pyodbc: 4.0.34
  • OS: Ubuntu 20.04
  • DB: Azure SQL Server
  • driver: msodbcsql17 (17.10)

Issue

When using the latest version of pyodbc (4.0.34) connecting to an Azure SQL Server with an access token a segmentation fault occurs. The same code does not produce a segmentation fault when running on 4.0.32.

Repro

Create an Azure SQL Server with AAD Auth enabled and your login as the server admin:

# Unique server name
SERVER_NAME=""
# Your public IP Address to add the firewall rule
PUBLIC_IP=""

az group create \
    --name issue-repro \
    --location centralus

az sql server create \
    --enable-ad-only-auth \
    --external-admin-principal-type User \
    --external-admin-name "$(az ad signed-in-user show --query "mail" --out tsv)" \
    --external-admin-sid "$(az ad signed-in-user show --query "objectId" --out tsv)" \
    --resource-group issue-repro \
    --name $SERVER_NAME

az sql server firewall-rule create \
    --resource-group issue-repro \
    --server $SERVER_NAME \
    --start-ip-address $PUBLIC_IP \
    --end-ip-address $PUBLIC_IP  \
    --name "Client IP"

The following will produce a segmentation fault on version 4.0.34 of pyodbc, but print “Connected” on version 4.0.32.

import struct

import pyodbc
from azure.identity import DefaultAzureCredential

server_address = "<server name>.database.windows.net"
azure_credential = DefaultAzureCredential()

# From https://github.com/mkleehammer/pyodbc/wiki/Connecting-to-SQL-Server-from-Linux
token_bytes = azure_credential.get_token("https://database.windows.net/").token.encode(
    "utf-16-le"
)
token_struct = struct.pack(f"<I{len(token_bytes)}s", len(token_bytes), token_bytes)
SQL_COPT_SS_ACCESS_TOKEN = (
    1256  # This connection option is defined by microsoft in msodbcsql.h
)


with pyodbc.connect(
    f"Driver={{ODBC Driver 17 for SQL Server}};Server={server_address};",
    attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct},
) as conn:
    print("Connected")

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 30 (9 by maintainers)

Most upvoted comments

I think I found a hint to the problem in the build wheel pipeline: it installs unixodbc-dev using apt-get install unixodbc-dev, and the version that it finds is: Get:7 http://deb.debian.org/debian stretch/main amd64 unixodbc-dev amd64 2.3.4-1 [249 kB]

https://github.com/mkleehammer/pyodbc/runs/7347636270?check_suite_focus=true#step:3:216

From what @v-chojas said, it sounds like the problem is that it installed a version older than 2.3.5, which seems to be the case ^. Though not sure if it’s supposed to include binaries in the wheel.

python --version

What are you actually using…?

IIRC, python --version returns a short response like Python 3.11.0.

python -VV

(that’s double uppercase letter V) would be more informative. From within Python code, that would be

print(sys.version)

I can consistently reproduce this with 4.0.34 and it goes away after downgrade to 4.0.32

/usr/local/lib/python3.9/multiprocessing/resource_tracker.py:216: UserWarning: resource_tracker: There appear to be 1 leaked semaphore objects to clean up at shutdown                                                                                                                       
  warnings.warn('resource_tracker: There appear to be %d '