fail to refresh when mapper properties or other ORM constructs were
added to the mapper/class after these accessors were first called.
+ .. change:: 3762
+ :tags: bug, mssql
+ :tickets: 3762
+ :versions: 1.1.4
+
+ Fixed bug in pyodbc dialect (as well as in the mostly non-working
+ adodbapi dialect) whereby a semicolon present in the password
+ or username fields could be interpreted as a separator for another
+ token; the values are now quoted when semicolons are present.
+
.. changelog::
:version: 1.0.15
:released: September 1, 2016
opts.update(url.query)
keys = opts
+
query = url.query
connect_args = {}
if 'odbc_connect' in keys:
connectors = [util.unquote_plus(keys.pop('odbc_connect'))]
else:
+ def check_quote(token):
+ if ";" in str(token):
+ token = "'%s'" % token
+ return token
+
+ keys = dict(
+ (k, check_quote(v)) for k, v in keys.items()
+ )
+
dsn_connection = 'dsn' in keys or \
('host' in keys and 'database' not in keys)
if dsn_connection:
keys.pop("odbc_autotranslate"))
connectors.extend(['%s=%s' % (k, v) for k, v in keys.items()])
+
return [[";".join(connectors)], connect_args]
def is_disconnect(self, e, connection, cursor):
from sqlalchemy.testing import eq_, engines
from sqlalchemy import *
from sqlalchemy import exc
-from sqlalchemy.dialects.mssql import pyodbc, pymssql
+from sqlalchemy.dialects.mssql import pyodbc, pymssql, adodbapi
from sqlalchemy.engine import url
from sqlalchemy.testing import fixtures
from sqlalchemy import testing
eq_([['DRIVER={SQL Server};Server=hostspec;Database=database;UI'
'D=username;PWD=password'], {}], connection)
+ def test_pyodbc_token_injection(self):
+ token1 = "someuser%3BPORT%3D50001"
+ token2 = "somepw%3BPORT%3D50001"
+ token3 = "somehost%3BPORT%3D50001"
+ token4 = "somedb%3BPORT%3D50001"
+
+ u = url.make_url(
+ 'mssql+pyodbc://%s:%s@%s/%s?driver=foob' % (
+ token1, token2, token3, token4
+ )
+ )
+ dialect = pyodbc.dialect()
+ connection = dialect.create_connect_args(u)
+ eq_(
+ [[
+ "DRIVER={foob};Server=somehost%3BPORT%3D50001;"
+ "Database=somedb%3BPORT%3D50001;UID='someuser;PORT=50001';"
+ "PWD='somepw;PORT=50001'"], {}],
+ connection
+ )
+
+ def test_adodbapi_token_injection(self):
+ token1 = "someuser%3BPORT%3D50001"
+ token2 = "somepw%3BPORT%3D50001"
+ token3 = "somehost%3BPORT%3D50001"
+ token4 = "someport%3BPORT%3D50001"
+
+ # this URL format is all wrong
+ u = url.make_url(
+ 'mssql+adodbapi://@/?user=%s&password=%s&host=%s&port=%s' % (
+ token1, token2, token3, token4
+ )
+ )
+ dialect = adodbapi.dialect()
+ connection = dialect.create_connect_args(u)
+ eq_(
+ [["Provider=SQLOLEDB;"
+ "Data Source='somehost;PORT=50001', 'someport;PORT=50001';"
+ "Initial Catalog=None;User Id='someuser;PORT=50001';"
+ "Password='somepw;PORT=50001'"], {}],
+ connection
+ )
+
def test_pymssql_port_setting(self):
dialect = pymssql.dialect()