buffer overrun when getting error message

19 views
Skip to first unread message

piotr.f...@starburstdata.com

unread,
Dec 15, 2017, 9:13:27 AM12/15/17
to pyodbc
Hi,

I am using pyodbc to connecto with Presto using an ODBC driver.
At times, Presto can produce quite long error message and this can come from pyodbc as:

pyodbc.Error: ('HY000', "[HY000] [Teradata][Presto] (1060) Presto Query Error: line 1:9: extraneous input ''' expecting {<EOF>, '.', ',', '[', 'ADD', 'ADMIN', 'ALL', 'ANALYZE', 'AND', 'ANY', 'ARRAY', 'AS', 'ASC', 'AT', 'BERNOULLI', 'BETWEEN', 'CALL', 'CASCADE', 'CATALOGS', 'COALESCE', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'CURRENT', 'DATA', 'DATE', 'DAY', 'DESC', 'DISTRIBUTED', 'EXCEPT', 'EXCLUDING', 'EXPLAIN', 'FILTER', 'FIRST', 'FOLLOWING', 'FORMAT', 'FROM', 'FUNCTIONS', 'GRANT', 'GRANTED', 'GRANTS', 'GRAPHVIZ', 'GROUP', 'HAVING', 'HOUR', 'IF', 'IN', 'INCLUDING', 'INPUT', 'INTEGER', 'INTERSECT', 'INTERVAL', 'IS', 'ISOLATION', 'LAST', 'LATERAL', 'LEVEL', 'LIKE', 'LIMIT', 'LOGICAL', 'MAP', 'MINUTE', 'MONTH', 'NFC', 'NFD', 'NFKC', 'NFKD', 'NO', 'NONE', 'NOT', 'NULLIF', 'NULLS', 'ONLY', 'OPTION', 'OR', 'ORDER', 'ORDINALITY', 'OUTPUT', 'OVER', 'PARTITION', 'PARTITIONS', 'POSITION', 'PRECEDING', 'PRIVILEGES', 'PROPERTIES', 'PUBLIC', 'RANGE', 'READ', 'RENAME', 'REPEATABLE', 'REPLACE', 'RESET', 'RESTRICT', 'REVOKE', 'ROLE', 'ROL\x00\x00\x00\x00HY000\x00\x98ܷᴙ蕢\uffff\x00\x00\x00⤨ᇂ\x01\x00峨ᇁ\x01\x00뿞ᅟ\x01\x00⤘ᇂ\x01\x00螰\ue007翾\x00ⷛᅟ\x01\x00\uffff\x00\x00\x00\uffff\x00\x00\x00蠐\ue007翾\x00ﭼᅞ\x01\x00蠐\ue007翾\x00ភ࿂\x01\x00蟰\ue007翾\x00⿆\u0fbd\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00푘㡞羫\x00栨ᇄ\x01\x00䅠ᇅ\x01\x00\x01\x00\x00\x00衰\ue007翾\x00歉ྼ\x01\x00꘠ᇄ\x01\x00\x07\x00\x00\x00ダᇅ\x01\x00⤘ᇂ\x01\x00\uf5b0ᅞ\x01\x00裘\ue007翾\x00푘㡞羫\x00푐㡞羫\x00\x00\x00\x00\x00\x01\x00\x00\x00裀\ue007翾\x00뇚࿂\x01\x00裀\ue007翾\x00ꪖ࿂\x01\x00꘠ᇄ\x01\x00\uf10a㤅羫\x00\x01\x00\x00\x00푠㡞羫\x00裘\ue007翾\x00\x10\x00\x00\x00訐\ue007翾\x00䂧࿂\x01\x00ӈဤ\x01\x00푠㡞羫\x00푐㡞羫\x00颎ྼ\x01\x00糠\u0fe8\x01\x00\x11\x00\x00\x00\u2d68ᆛ\x01\x00覐\ue007翾\x00啑鏶䀧\ue633粰\u0fe8\x01\x00迀ᇃ\x01\x00冈㤆羫\x00\x1f\x00\x00\x00\x00\x00\x00\x00퐸㡞羫\x00\x00\x00\x00\x00蠐ᇁ\x01\x00啑鏶\uffff\uffffⱸᆛ\x01\x00랆ྻ\x01\x00\x00\x00\x00\x00泀ྼ\uffff\uffff\x00\x00\x00\x00\uf030㤅羫\x00튰㡞羫\x00\uf102㤅羫\x00\ue600㢂羫\x00툸㡞羫\x00觐\ue007翾\x00\ued28࿅\x01\x00尠࿏\x01\x00\x00\x00\x00\x00觰\ue007翾\x00\uee23࿅\x01\x00\x98ܷᴙ蕢\x03\x00\x00\x00툸㡞羫\x00툸㡞羫\x00\x00\x00\x00\x00蠐ᇁ\x01\x00誰\ue007翾\x00뤼࿂\x01\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00펰㡞羫\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00沈ᅌ\x02\x00蠐ᇁ\x01\x00툸㡞羫\x00\x02\x00\x00\x00\ue600㢂羫\x00\x00\x00\x00\x00鸘ᇁ\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00끠\u0fe1\x01\x00謠\ue007翾\x00ⶡ࿂\x01\x00예ᇃ\x01\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ৰᄱ\x01\x00\x02\x00\x00\x00엨ᇃ\x01\x00诀\ue007翾\x00\uf106ྺ\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\uf09cྺ\x01\x00煝ఠ굙꣰\x02\x00\x00\x00엨ᇃ\x01\x00였ᇃ\x01\x00\x00\x00\x00\x00끈 (1060) (SQLExecDirectW)")

I.e. assuming "[HY000] " and " (1060) (SQLExecDirectW)" is something added by pyodbc itself, this is 1023 bytes of actual error message, followed by garbage, which looks like a buffer overrun, somewhere

I tried to reproduce the same problem with C program calling ODBC directly, but I could not. -- This is not to say the ODBC driver is correct, only that I could prove it being incorrect.

Is it possible that pyodbc does buffer overrun when pulling long error message from a driver?

Best regards,
Piotr

piotr.f...@gmail.com

unread,
Dec 15, 2017, 10:00:50 AM12/15/17
to pyodbc
Hi again,

I took time to read pyodbc code and odbc & python API reference and it seems that:

pyodbc calls SQLGetDiagRecW and gets error message (szMsg) & total error message available length (cchMsg)

cchMsg can be greater than total size of szMsg, since cchMsg is the length of the whole error message, not the number of characters (SQLWCHAR) written to the buffer

Then pyodbc calls PyUnicode_Decode, asking Python to decode cchMsg*sizeof(WCHAR) bytes from szMsg -- i.e. potentially more bytes than there are in szMsg, thus reading after szMsg ends.

Best
Piotr
Reply all
Reply to author
Forward
0 new messages