0

Визуальное приложение FoxPro вызывает Postgres драйвер psqlodbc 9.3.0400 Оба 32 битное приложение работает в ОС Windows 7 x64Как исправить переполнение буфера в psqlodbc драйвера

Этот вызов вызывает буфер Ovverrun исключение в psqlodbc35w.dll с трассировки стека ниже , Как исправить проблему? psqlodbc - это приложение с открытым исходным кодом, написанное на языке C и, возможно, скомпилированное Visual Studio. Возможно, это возможно в некоторых случаях, так что исключение не происходит? Установлена ​​версия Visual Studio 2015 Community Edition.

После сбоя вызывается отладчик Visual Studio 2015 Community Edition. Он показывает трассировку стека:

> psqlodbc35w.dll!__crt_debugger_hook()  Unknown 
    psqlodbc35w.dll!__report_gsfailure() Line 315 + 0x7 bytes C 
    psqlodbc35w.dll!SC_create_errorinfo(const StatementClass_ * self) Line 1423 + 0xa bytes C 
    psqlodbc35w.dll!PGAPI_StmtError(void * hstmt, short RecNumber, unsigned char * szSqlState, long * pfNativeError, unsigned char * szErrorMsg, short cbErrorMsgMax, short * pcbErrorMsg, unsigned short flag) Line 1612 C 
    psqlodbc35w.dll!PGAPI_GetDiagField(short HandleType, void * Handle, short RecNumber, short DiagIdentifier, void * DiagInfoPtr, short BufferLength, short * StringLengthPtr) Line 280 C 
    psqlodbc35w.dll!SQLGetDiagFieldW(short fHandleType, void * handle, short iRecord, short fDiagField, void * rgbDiagInfo, short cbDiagInfoMax, short * pcbDiagInfo) Line 374 + 0x16 bytes C 
    odbc32(dot)dll!_VFreeErrors(at)4() + 0x401f bytes  
    odbc32(dot)dll!_SearchStatusCode(at)8() + 0x25 bytes  
    odbc32(dot)dll!_IsStmtPositioned(at)4() + 0x14 bytes  
    odbc32(dot)dll!_SQLExecute(at)4() - 0xfd3e bytes  
    odbc32(dot)dll!_SQLExecDirect(at)12() + 0x77 bytes  
    vfp9r.dll!0c3904c6()  
... 

окно Debug показывает много загруженных moduled и в конце:

... 
The thread 'Win32 Thread' (0x2778) has exited with code 0 (0x0). 
A buffer overrun has occurred in alguss.EXE which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program. 
For more details please see Help topic 'How to debug Buffer Overrun Issues'. 

Опубликовано также в http://www.postgresql.org/message-id/[email protected]

Update

Вот FoxPro код который вызывает сбой. Сбой возникает в драйвере odbc, прежде чем запрос отправляется в Postgres. Таблицы в запросе не обязательно должны присутствовать в базе данных. Просто запустите запрос, используя официальный драйвер postgres odbc. Возможно, использование $ characters в запросе вызывает сбой odbc. Строка

SET TEXTMERGE ON 
SET TEXTMERGE TO (sys(2015)) 
TEXT TEXTMERGE NOSHOW 

CREATE or replace FUNCTION public.f_infA() 
    RETURNS TABLE (
kuupaev date, 
nimi text, 
tasudok text, 

regnr text, 
kmprotsent text, 
neto numeric, 
myyk numeric, 
erisus01 bool, 
erisus02 bool, 
erisus03 bool 
) AS $f_InfA$ 

WITH 
myyk as (

SELECT 
    dok.kuupaev, 
    dok.tasudok, 
    klient.regnr, 
    CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi, 
    20 as kmprotsent, 
    k01+k011+k01erik as myyk20, 
    0 as myyk9, 

    MAX(klient.nimi)::char(80) as maxnimi, 
    bool_or(k01erik<>0) as erisus01, 
    bool_or(d09<>0) as erisus02, 

    SUM( ROUND(rid.hind * case when rid.kogus<>0 then rid.kogus else 1 end* 
    CASE when rid.kogpak<>0 then rid.kogpak else 1 end 
    /case when dok.doktyyp<>'Y' then 1 else 1+myygikoo.kmprotsent/100 end * 
    CASE when dok.raha=prpalk.pohiraha then 1 
     when dok.exchrate<>0 then dok.Exchrate else kurss.kurss end,2) 
    ) as neto 

FROM prpalk, tehing 
JOIN dok ON tehing.dokumnr=dok.dokumnr 
JOIN rid ON dok.dokumnr=rid.dokumnr 
JOIN klient ON dok.klient=klient.kood 
LEFT JOIN myygikoo ON rid.myygikood=myygikoo.myygikood or (rid.myygikood is null and myygikoo.myygikood ='') 
LEFT JOIN kurss ON dok.raha=kurss.raha AND dok.kuupaev=kurss.kuupaev 
LEFT JOIN toode ON rid.toode=toode.toode 
WHERE (rid.toode is null or toode.grupp<>'S' OR rid.toode='LE' or (toode.klass like '%T%' AND toode.klass not like '%E%' 
    AND toode.klass not like '%M%')) and 
    tehing.alusdok='LG' AND ((k01+k011+k01erik)<>0 ) 
AND klient.nimi not ilike '%AUDIITORBÜROO%' 
AND klient.nimi not ilike '%ADVOKAADIBÜROO%' 
AND klient.nimi not ilike 'Notar %' 
AND klient.nimi not ilike '% Notar' 
AND rid.hind <> 0  -- Et ei tekiks arvetel taara 0 hinnaga väljastamisel erisuse koodi 03 
AND klient.nimi not ilike 'Eraisik' 
AND klient.nimi not ilike 'Jaeostja' 
and not klient.kmdkeeld 

GROUP BY 1,2,3,4,5,6,7 
union all 
SELECT 
    dok.kuupaev, 
    dok.tasudok, 
    klient.regnr, 
    CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi, 
    9, 
    0 as myyk20, 
    k02+k021 as myyk9, 

    MAX(klient.nimi)::char(80) as maxnimi, 
    bool_or(k01erik<>0) as erisus01, 
    bool_or(d09<>0) as erisus02, 

    SUM( ROUND(rid.hind * case when rid.kogus<>0 then rid.kogus else 1 end* 
    CASE when rid.kogpak<>0 then rid.kogpak else 1 end 
    /case when dok.doktyyp<>'Y' then 1 else 1+myygikoo.kmprotsent/100 end * 
    CASE when dok.raha=prpalk.pohiraha then 1 
     when dok.exchrate<>0 then dok.Exchrate else kurss.kurss end,2) 
    ) as neto 

FROM prpalk, tehing 
JOIN dok ON tehing.dokumnr=dok.dokumnr 
JOIN rid ON dok.dokumnr=rid.dokumnr 
JOIN klient ON dok.klient=klient.kood 
LEFT JOIN myygikoo ON rid.myygikood=myygikoo.myygikood or (rid.myygikood is null and myygikoo.myygikood ='') 
LEFT JOIN kurss ON dok.raha=kurss.raha AND dok.kuupaev=kurss.kuupaev 
LEFT JOIN toode ON rid.toode=toode.toode 
WHERE (rid.toode is null or toode.grupp<>'S' OR rid.toode='LE' or (toode.klass like '%T%' AND toode.klass not like '%E%' 
    AND toode.klass not like '%M%')) and 
    tehing.alusdok='LG' AND (k02+k021)<>0 
AND klient.nimi not ilike '%AUDIITORBÜROO%' 
AND klient.nimi not ilike '%ADVOKAADIBÜROO%' 
AND klient.nimi not ilike 'Notar %' 
AND klient.nimi not ilike '% Notar' 
AND rid.hind <> 0  -- Et ei tekiks arvetel taara 0 hinnaga väljastamisel erisuse koodi 03 
AND klient.nimi not ilike 'Eraisik' 
AND klient.nimi not ilike 'Jaeostja' 
and not klient.kmdkeeld 
GROUP BY 1,2,3,4,5,6,7 
union all 
SELECT 
    omrid.adkuupaev, 
    omrid.ettemarve, 
    klient.regnr, 
    CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi, 

    CASE when sum(k01+k011+k01erik)<>0 then 20 else 9 end, 

    CASE when sum(k01+k01erik+k011)<>0 then 

    sum(ROUND( 
    case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end * 
    case when omrid.kogus<>0 then omrid.kogus else 1 end * 
    case when omrid.raha=prpalk.pohiraha then 1 else 
     case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2)) 

    else 0 end as myyk20, 


    CASE when sum(k02+k021)<>0 then 

sum( ROUND( 
    case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end * 
    case when omrid.kogus<>0 then omrid.kogus else 1 end * 
    case when omrid.raha=prpalk.pohiraha then 1 else 
     case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2)) 

    else 0 end as myyk9, 

    MAX(klient.nimi)::char(80) as maxnimi, 
    bool_or(k01erik<>0) as erisus01, 
    bool_or(d09<>0) as erisus02, 

    SUM(ROUND( 
    case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end * 
    case when omrid.kogus<>0 then omrid.kogus else 1 end * 
    case when omrid.raha=prpalk.pohiraha then 1 else 
     case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2)) as neto 
FROM prpalk, tehing 
join omdok on tehing.dokumnr=omdok.dokumnr 
JOIN omrid ON omrid.dokumnr=tehing.dokumnr -- AND tehing.doknr=omrid.ettemarve 
JOIN klient ON omdok.klient=klient.kood 
LEFT JOIN kurss ON omrid.raha=kurss.raha AND omrid.adkuupaev=kurss.kuupaev 

WHERE tehing.alusdok in ('DT', 'DI') AND ((k01+k01erik+ k011)>0) 
    and omrid.ettemarve is not null and omrid.ettemarve is distinct from '' 
    AND klient.nimi not ilike '%AUDIITORBÜROO%' 
    AND klient.nimi not ilike '%ADVOKAADIBÜROO%' 
    AND klient.nimi not ilike 'Notar %' 
    AND klient.nimi not ilike '% Notar' 
    and not klient.kmdkeeld 
GROUP BY 1,2,3,4 

), 

myyk1000 as (
SELECT 
    regnr, 
    nimi 
FROM myyk 
WHERE neto>0 
GROUP BY 1,2 
HAVING SUM(neto)>1000 
) 

SELECT 
    myyk.kuupaev, 
    myyk.maxnimi as nimi, 
    myyk.tasudok, 

    myyk.regnr, 
    '20' as kmprotsent, 
    round(SUM(myyk.neto),2) as neto, 
    round(SUM(myyk.myyk20),2) as myyk, 
    bool_or(erisus01) as erisus01, 
    bool_or(erisus02) as erisus02, 
    bool_or(myyk.kmprotsent=0) as erisus03 

FROM myyk1000 
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi 
GROUP BY 1,2,3,4 
HAVING SUM(myyk.myyk20)<>0 

UNION ALL 

SELECT 
    myyk.kuupaev, 
    myyk.maxnimi as nimi, 
    myyk.tasudok, 
    myyk.regnr, 
    '9', 
    round(SUM(myyk.neto),2) , 
    round(SUM(myyk.myyk9),2), 
    false, 
    bool_or(erisus02) as erisus02, 
    bool_or(myyk.kmprotsent=0) as erisus03 

FROM myyk1000 
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi 
GROUP BY 1,2,3,4 
HAVING SUM(myyk.myyk9)<>0 

UNION ALL 

SELECT 
    myyk.kuupaev, 
    myyk.maxnimi as nimi, 
    myyk.tasudok, 

    myyk.regnr, 
    'erisus20', 
    round(SUM(myyk.neto),2) , 
    round(SUM(myyk.myyk9),2), 
    false, 
    bool_or(erisus02) as erisus02, 
    false as erisus03 

FROM myyk1000 
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi 
GROUP BY 1,2,3,4 
HAVING bool_or(erisus02) 
ORDER BY nimi, kuupaev, tasudok 

$f_infa$ LANGUAGE sql STABLE; 

RESET ROLE; 

ENDTEXT 

cSqlFail = SET('textmerge',2) 
SET TEXTMERGE TO 
SQLEXEC(m.g_server.nConnhandle, FILETOSTR(m.cSqlFail)) 

соединение используется:

cConnString = "DRIVER={PostgreSQL Unicode};"+ ; 
    "DATABASE=test";"+ ; 
    "SERVER=localhost;" + ; 
    "PORT=5432;" + ; 
    "UID=user;" + ; 
    "Protocol=-0;" + ; 
    "B9=0"+ ; 
    ";SSLMODE=allow" 
+0

"visual foxpro"? Надеюсь, вы работаете над переходом на что-то поддерживаемое и текущее. Тем не менее, psqlODBC не должен терпеть крах, так что возможно (не обязательно) ошибка psqlODBC. Трудно точно сказать, что без воспроизводимого тестового примера. –

+0

Миграция не планируется. Я разместил журналы в http://pgfoundry.org/tracker/?func = detail & atid = 538 & aid = 1002767 & group_id = 1000125. Можно загрузить тестовый файл (exe и dll-файлы, вызывающие psqlodbc). Или я могу попытаться отладить это и скомпилировать psqlodbc на моем компьютере, используя редакцию сообщества Visual Studio 2015, если я знаю, что менять – Andrus

+0

Я использую ту же версию без ошибок на win7 x64. –

ответ

3

(я пишу здесь, как я не могу отформатировать его в комментариях, и это оказывается грязный)

Да, ваш код вызывает аварии. Похоже, что это ошибка в драйвере, я ожидаю, что он вернет ошибку, но не заставит VFP прекратить выполнение.

Ваш код не запускался ни с pgsl, ни с консоли SQL. Ошибка я получил:

227: ERROR: unterminated dollar-quoted string at or near "$f_InfA$ 

и он указал также здесь:

"ESET ROLE; 
LINE 14:) AS $f_InfA$ 

IOW вы уже имели ошибку в той цитате, где ваш доллар кавычках не был расторгнут. Если это не опечатка в коде, который вы указали здесь, у вас есть:

... bool 
) AS $f_InfA$ 

... 

$f_infa$ LANGUAGE sql STABLE; 

RESET ROLE; 

в вашем коде. Поскольку строки, цитируемые в долларах, чувствительны к регистру, как и в XML, они не уничтожаются. Второй должен быть также «$ f_InfA $».

Сделать это просто $$ или $ f_InfA $, оба должны работать.

Водитель не должен вызывать сбоев. HTH