gpt4 book ai didi

visual-studio - 如何修复 psqlodbc 驱动程序中的缓冲区溢出

转载 作者:行者123 更新时间:2023-11-29 14:19:53 24 4
gpt4 key购买 nike

Visual FoxPro 应用程序调用 Postgres psqlodbc 驱动程序 9.3.0400两者都是在 Windows 7 x64 上运行的 32 位应用程序

此调用导致 psqlodbc35w.dll 中的 Buffer Ovverrun 异常,堆栈跟踪如下。如何解决这个问题? 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()
...

调试窗口显示大量加载的模块并在末尾:

...
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/1B88854920C942948F943E26B452E3A4@dell2

更新

这是导致崩溃的 FoxPro 代码。在将查询发送到 Postgres 之前,odbc 驱动程序发生崩溃。查询中的表不需要存在于数据库中。只需使用 postgres odbc 官方驱动程序运行查询。可能在查询中使用 $ 字符会导致 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"

最佳答案

(我在这里写是因为我不能在评论中格式化它,结果很乱)

是的,您的代码会导致崩溃。看起来这是驱动程序中的错误,我希望它返回错误但不会导致 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$ 两者,它应该可以工作。

虽然驱动程序不应该导致崩溃。

关于visual-studio - 如何修复 psqlodbc 驱动程序中的缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32650613/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com