Re: libpq bug? - Mailing list pgsql-general

From patrick keshishian
Subject Re: libpq bug?
Date
Msg-id CAN0yQBrsGnusXkCbE9NNAhJ=QZva3KjZ-S+k723Pk=6S_0bqkQ@mail.gmail.com
Whole thread Raw
In response to Re: libpq bug?  (Igor Korot <ikorot01@gmail.com>)
Responses Re: libpq bug?
List pgsql-general
On Fri, Dec 28, 2018 at 3:07 PM Igor Korot <ikorot01@gmail.com> wrote:
Hi,

On Fri, Dec 28, 2018 at 4:51 PM patrick keshishian <pkeshish@gmail.com> wrote:
>
>
> On Fri, Dec 28, 2018 at 2:00 PM Igor Korot <ikorot01@gmail.com> wrote:
>>
>> Hi, ALL,
>> Following code:
>>
>> int PostgresDatabase::GetTableOwner (const std::wstring &schemaName,
>> const std::wstring &tableName, std::wstring &owner,
>> std::vector<std::wstring> &errorMsg)
>> {
>>    int result = 0;
>>     std::wstring query = L"SELECT u.usename FROM pg_class c, pg_user
>> u, pg_namespace n WHERE n.oid = c.relnamespace AND u.usesysid =
>> c.relowner AND n.nspname = $1 AND relname = $2";
>>     char *values[2];
>>     values[0] = NULL, values[1] = NULL;
>>     values[0] = new char[schemaName.length() + 1];
>>     values[1] = new char[tableName.length() + 1];
>>     memset( values[0], '\0', schemaName.length() + 1 );
>>     memset( values[1], '\0', tableName.length() + 1 );
>>     strcpy( values[0], m_pimpl->m_myconv.to_bytes( schemaName.c_str()
>> ).c_str() );
>>     strcpy( values[1], m_pimpl->m_myconv.to_bytes( tableName.c_str()
>> ).c_str() );
>>     int len1 = (int) schemaName.length();
>>     int len2 = (int) tableName.length();
>>     int length[2] = { len1, len2 };
>>     int formats[2] = { 1, 1 };
>>     PGresult *res = PQexecParams( m_db, m_pimpl->m_myconv.to_bytes(
>> query.c_str() ).c_str(), 2, NULL, values, length, formats, 1 );
>>     ExecStatusType status = PQresultStatus( res );
>>     if( status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK )
>>     {
>>         result = 1;
>>         std::wstring err = m_pimpl->m_myconv.from_bytes(
>> PQerrorMessage( m_db ) );
>>         errorMsg.push_back( L"Error executing query: " + err );
>>         PQclear( res );
>>     }
>>     else
>>     {
>>         owner = m_pimpl->m_myconv.from_bytes( PQgetvalue( res, 0, 0 ) );
>>     }
>>     return result;
>> }
>>
>> when ran with the call of
>>
>> GetTableOwner( "public", "abcß", owner, errorMsg );
>>
>> returns:
>>
>> ERROR: Invalid byte sequence for encoding UTF8.
>>
>> Does this mean I found the bug in the library?
>
>
> The bug is in your C++ code. "abcß" as tableName.lenght() (wstring) returns 4 (as in four characters) not number of bytes required to represent the intended string: 61 62 63 c3 9f
> Since the last character is a 2 bytes in length. Therefore, your call to PQexecParams() specifies a shorter length and hence an invalid UTF-8 sequence.
>
> Furthermore, your value[] array allocation is in error since wstring::length returns number of characters, not number of bytes. so you will end up with buffer-overflows.

So I should use
https://stackoverflow.com/questions/9278723/how-can-i-get-the-byte-size-of-stdwstring
in both places?

size() also returns 4. If you multiply it with sizeof(wchar_t) you will end up with maximum buffers size necessary to hold the string (minus terminating \0), but not the correct length you are after. I am unsure of the "correct" C++ solution.

Sorry,
--patrick

 
Thank you.

>
> HTH,
> --patrick
>
>
>>
>> Any idea what I can do?
>>
>> Thank you.
>>

pgsql-general by date:

Previous
From: Adrian Klaver
Date:
Subject: Re: In which session context is a trigger run?
Next
From: Mark Fletcher
Date:
Subject: ERROR: found multixact XX from before relminmxid YY