Обсуждение: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

Поиск
Список
Период
Сортировка

Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Boszormenyi Zoltan
Дата:
Hi,

we had to recently test psqlODBC with an older application
which doesn't expect ODBC 3.x.

The problem is that the client locks up as soon as it encounters
an error of any kind, like restarting the server from under the client
or simply executing a bad query.

After debugging the problem and reading the code of both
unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
I discovered that the DriverManager calls the driver's SQLError()
and SQLGetDiagRec() in a loop and expects it to return the error
message in pieces and when there is nothing left to return,
these driver methods must return some SQL error instead of
SQL_SUCCESS[_WITH_INFO]. SQLGetDiagRec() does this properly
because the DriverManager keeps track of the pieces via the
RecNumber argument but SQLError() calls PGAPI_StmtError()
with RecNumber == -1 every time. Instead, it uses the internal
error structure to keep track of the string left to return. SQLError()
calls PGAPI_StmtError() with
   flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR
which means that ER_ReturnError() may free the error structure.

The interaction between the looping and the freeing of the error
structure is buggy, the error makes it go into an infinite loop.

The attached patch fixes this problem. Though, I am not sure about
whether the (stapos > msglen) and (error->errorpos >= msglen)
checks are redundant or not.

Best regards,
Zoltán Böszörményi

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de
      http://www.postgresql.at/


Вложения

Re: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Hiroshi Inoue
Дата:
Hi,

(2012/08/31 20:21), Boszormenyi Zoltan wrote:
> Hi,
>
> we had to recently test psqlODBC with an older application
> which doesn't expect ODBC 3.x.
>
> The problem is that the client locks up as soon as it encounters
> an error of any kind, like restarting the server from under the client
> or simply executing a bad query.
>
> After debugging the problem and reading the code of both
> unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
> I discovered that the DriverManager calls the driver's SQLError()
> and SQLGetDiagRec() in a loop

Does the DriverManager call both SQLError() and SQLGetDiagRec()?
Could you send me (loop part of) the Mylog output?

regards,
Hiroshi Inoue

 > and expects it to return the error
> message in pieces and when there is nothing left to return,
> these driver methods must return some SQL error instead of
> SQL_SUCCESS[_WITH_INFO]. SQLGetDiagRec() does this properly
> because the DriverManager keeps track of the pieces via the
> RecNumber argument but SQLError() calls PGAPI_StmtError()
> with RecNumber == -1 every time. Instead, it uses the internal
> error structure to keep track of the string left to return. SQLError()
> calls PGAPI_StmtError() with
>    flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR
> which means that ER_ReturnError() may free the error structure.
>
> The interaction between the looping and the freeing of the error
> structure is buggy, the error makes it go into an infinite loop.
>
> The attached patch fixes this problem. Though, I am not sure about
> whether the (stapos > msglen) and (error->errorpos >= msglen)
> checks are redundant or not.
>
> Best regards,
> Zoltán Böszörményi


Re: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Boszormenyi Zoltan
Дата:
Hi,

2012-09-01 11:19 keltezéssel, Hiroshi Inoue írta:
> Hi,
>
> (2012/08/31 20:21), Boszormenyi Zoltan wrote:
>> Hi,
>>
>> we had to recently test psqlODBC with an older application
>> which doesn't expect ODBC 3.x.
>>
>> The problem is that the client locks up as soon as it encounters
>> an error of any kind, like restarting the server from under the client
>> or simply executing a bad query.
>>
>> After debugging the problem and reading the code of both
>> unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
>> I discovered that the DriverManager calls the driver's SQLError()
>> and SQLGetDiagRec() in a loop
>
> Does the DriverManager call both SQLError() and SQLGetDiagRec()?

Yes, it detects which is supported and calls that in the error handler part
of SQLExecute(). In case psqlODBC is compiled using --with-odbcver=0x0250,
SQLGetDiagRec() is naturally not supported.

> Could you send me (loop part of) the Mylog output?

I attached the unixODBC tracefile (/tmp/Trace.txt), there is no "mylog"
lines in it. I execute a single "select * from test;" and this table doesn't exist.
The trace file shows that the error code is repeated ad infinitum.

But for my debugging, I didn't use the ODBC tracing, I added my extra printf()s
so I can see on the client terminal what is going on.

I wrote:
>> The attached patch fixes this problem. Though, I am not sure about
>> whether the (stapos > msglen) and (error->errorpos >= msglen)
>> checks are redundant or not.
>

----8<--------8<--------8<--------8<--------8<----
@@ -226,7 +226,17 @@ ER_ReturnError(PG_ErrorInfo **pgerror,
         }
         stapos = (RecNumber - 1) * error->recsize;
         if (stapos > msglen)
+       {
+               if (clear_str)
+               {
+                       if (error->errorpos >= msglen)
+                       {
+                               ER_Destructor(error);
+                               *pgerror = NULL;
+                       }
+               }
                 return SQL_NO_DATA_FOUND;
+       }
         pcblen = wrtlen = msglen - stapos;
         if (pcblen > error->recsize)
                 pcblen = error->recsize;
----8<--------8<--------8<--------8<--------8<----

It seems the two checks are indeed redundant, valgrind shows no leaks
which means ER_Destructor() is called so the second check must be true.

Best regards,
Zoltán Böszörményi

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de
      http://www.postgresql.at/


Вложения

Re: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Boszormenyi Zoltan
Дата:
Hi,

2012-09-01 17:22 keltezéssel, Boszormenyi Zoltan írta:
Hi,

2012-09-01 11:19 keltezéssel, Hiroshi Inoue írta:
Hi,

(2012/08/31 20:21), Boszormenyi Zoltan wrote:
Hi,

we had to recently test psqlODBC with an older application
which doesn't expect ODBC 3.x.

The problem is that the client locks up as soon as it encounters
an error of any kind, like restarting the server from under the client
or simply executing a bad query.

After debugging the problem and reading the code of both
unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
I discovered that the DriverManager calls the driver's SQLError()
and SQLGetDiagRec() in a loop

Does the DriverManager call both SQLError() and SQLGetDiagRec()?

Yes, it detects which is supported and calls that in the error handler part
of SQLExecute(). In case psqlODBC is compiled using --with-odbcver=0x0250,
SQLGetDiagRec() is naturally not supported.

Could you send me (loop part of) the Mylog output?

I attached the unixODBC tracefile (/tmp/Trace.txt), there is no "mylog"
lines in it. I execute a single "select * from test;" and this table doesn't exist.
The trace file shows that the error code is repeated ad infinitum.

But for my debugging, I didn't use the ODBC tracing, I added my extra printf()s
so I can see on the client terminal what is going on.

Attached is the mylog output for the vanilla psqlODBC 09.01.0200
which also shows the infinite loop.


I wrote:
The attached patch fixes this problem. Though, I am not sure about
whether the (stapos > msglen) and (error->errorpos >= msglen)
checks are redundant or not.


----8<--------8<--------8<--------8<--------8<----
@@ -226,7 +226,17 @@ ER_ReturnError(PG_ErrorInfo **pgerror,
        }
        stapos = (RecNumber - 1) * error->recsize;
        if (stapos > msglen)
+       {
+               if (clear_str)
+               {
+                       if (error->errorpos >= msglen)
+                       {
+                               ER_Destructor(error);
+                               *pgerror = NULL;
+                       }
+               }
                return SQL_NO_DATA_FOUND;
+       }
        pcblen = wrtlen = msglen - stapos;
        if (pcblen > error->recsize)
                pcblen = error->recsize;
----8<--------8<--------8<--------8<--------8<----

It seems the two checks are indeed redundant, valgrind shows no leaks
which means ER_Destructor() is called so the second check must be true.

Best regards,
Zoltán Böszörményi





-- 
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de    http://www.postgresql.at/
Вложения

Re: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Hiroshi Inoue
Дата:
Hi,

Sorry for the late reoly.

(2012/09/02 2:13), Boszormenyi Zoltan wrote:
> Hi,
>
> 2012-09-01 17:22 keltezéssel, Boszormenyi Zoltan írta:
>> Hi,
>>
>> 2012-09-01 11:19 keltezéssel, Hiroshi Inoue írta:
>>> Hi,
>>>
>>> (2012/08/31 20:21), Boszormenyi Zoltan wrote:
>>>> Hi,
>>>>
>>>> we had to recently test psqlODBC with an older application
>>>> which doesn't expect ODBC 3.x.
>>>>
>>>> The problem is that the client locks up as soon as it encounters
>>>> an error of any kind, like restarting the server from under the client
>>>> or simply executing a bad query.
>>>>
>>>> After debugging the problem and reading the code of both
>>>> unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
>>>> I discovered that the DriverManager calls the driver's SQLError()
>>>> and SQLGetDiagRec() in a loop
>>>
>>> Does the DriverManager call both SQLError() and SQLGetDiagRec()?
>>
>> Yes, it detects which is supported and calls that in the error handler
>> part
>> of SQLExecute(). In case psqlODBC is compiled using
>> --with-odbcver=0x0250,
>> SQLGetDiagRec() is naturally not supported.
>>
>>> Could you send me (loop part of) the Mylog output?
>>
>> I attached the unixODBC tracefile (/tmp/Trace.txt), there is no "mylog"
>> lines in it. I execute a single "select * from test;" and this table
>> doesn't exist.
>> The trace file shows that the error code is repeated ad infinitum.
>>
>> But for my debugging, I didn't use the ODBC tracing, I added my extra
>> printf()s
>> so I can see on the client terminal what is going on.
>
> Attached is the mylog output for the vanilla psqlODBC 09.01.0200
> which also shows the infinite loop.

Thanks.

Clearing error info seems to cause the infinite loop.

Simply removing the follwoing code would solve the bug.
COuld you try it?

        if (error->errorpos >= msglen)
        {
            ER_Destructor(error);
            *pgerror = NULL;
        }

regards,
Hiroshi Inoue



Re: Error reporting goes into an infinite loop when compiled --with-odbcver=0x0250

От
Boszormenyi Zoltan
Дата:
Hi,

2012-09-08 01:51 keltezéssel, Hiroshi Inoue írta:
Hi,

Sorry for the late reoly.

no problem, it seems you didn't receive the personal copies of
my mails. There seems to be a problem with reverse DNS
on your side of the of the globe, I got this for the mails in which
I sent the attachments:

---8<------8<------8<------8<------8<---
                   The mail system

<hiroshi@winpg.jp>: host winpg.jp[219.94.251.195] said: 450 4.7.1 Client host   rejected: cannot find your hostname, [87.118.86.135] (in reply to RCPT TO   command)
 
Reporting-MTA: dns; km31432.keymachine.de
X-Postfix-Queue-ID: 23F503900523
X-Postfix-Sender: rfc822; zb@cybertec.at
Arrival-Date: Fri, 31 Aug 2012 11:21:41 +0000 (UTC)

Final-Recipient: rfc822; hiroshi@winpg.jp
Original-Recipient: rfc822;hiroshi@winpg.jp
Action: failed
Status: 4.7.1
Remote-MTA: dns; winpg.jp
Diagnostic-Code: smtp; 450 4.7.1 Client host rejected: cannot find your   hostname, [87.118.86.135]
---8<------8<------8<------8<------8<---

(2012/09/02 2:13), Boszormenyi Zoltan wrote:
Hi,

2012-09-01 17:22 keltezéssel, Boszormenyi Zoltan írta:
Hi,

2012-09-01 11:19 keltezéssel, Hiroshi Inoue írta:
Hi,

(2012/08/31 20:21), Boszormenyi Zoltan wrote:
Hi,

we had to recently test psqlODBC with an older application
which doesn't expect ODBC 3.x.

The problem is that the client locks up as soon as it encounters
an error of any kind, like restarting the server from under the client
or simply executing a bad query.

After debugging the problem and reading the code of both
unixODBC 2.3.1 and psqlODBC (version 09.00.0310 and 09.01.0200),
I discovered that the DriverManager calls the driver's SQLError()
and SQLGetDiagRec() in a loop

Does the DriverManager call both SQLError() and SQLGetDiagRec()?

Yes, it detects which is supported and calls that in the error handler
part
of SQLExecute(). In case psqlODBC is compiled using
--with-odbcver=0x0250,
SQLGetDiagRec() is naturally not supported.

Could you send me (loop part of) the Mylog output?

I attached the unixODBC tracefile (/tmp/Trace.txt), there is no "mylog"
lines in it. I execute a single "select * from test;" and this table
doesn't exist.
The trace file shows that the error code is repeated ad infinitum.

But for my debugging, I didn't use the ODBC tracing, I added my extra
printf()s
so I can see on the client terminal what is going on.

Attached is the mylog output for the vanilla psqlODBC 09.01.0200
which also shows the infinite loop.

Thanks.

Clearing error info seems to cause the infinite loop.

Simply removing the follwoing code would solve the bug.
COuld you try it?

        if (error->errorpos >= msglen)
        {
            ER_Destructor(error);
            *pgerror = NULL;
        }

Yes, it also solved the infinite loop. But then using the
PODBC_ERROR_CLEAR flag in PGAPI_Error() is unneeded.
Nothing else checks for this flag. Attached is the new patch,
tested with Valgrind, no leaks found in psqlodbc. The only
leaks reported were inside isql and libreadline.


regards,
Hiroshi Inoue





-- 
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de    http://www.postgresql.at/
Вложения