Re: libpq bug? - Mailing list pgsql-general

From Igor Korot
Subject Re: libpq bug?
Date
Msg-id CA+FnnTw85P80PV5VYJebVWvZoDnM538sk6Qg9=6V44d6+rKYoQ@mail.gmail.com
Whole thread Raw
In response to Re: libpq bug?  (patrick keshishian <pkeshish@gmail.com>)
Responses Re: libpq bug?
List pgsql-general
Hi, Patrick,

Here is my new 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;
    int charlength1 = schemaName.length() * sizeof( wchar_t ),
charlength2 = tableName.length() * sizeof( wchar_t );
    values[0] = new char[schemaName.length() * sizeof( wchar_t ) + 1];
    values[1] = new char[tableName.length() * sizeof( wchar_t ) + 1];
    memset( values[0], '\0', schemaName.length()  * sizeof( wchar_t ) + 1 );
    memset( values[1], '\0', tableName.length() * sizeof( wchar_t ) + 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() * sizeof( wchar_t );
    int len2 = (int) tableName.length() * sizeof( wchar_t );
    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;
}

The charlength2 variable contains the value of 8 and I'm still getting
the same error.

Any idea?

Thank you.

On Fri, Dec 28, 2018 at 5:40 PM patrick keshishian <pkeshish@gmail.com> wrote:
>
> 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
ofbytes 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
andhence an invalid UTF-8 sequence. 
>> >
>> > Furthermore, your value[] array allocation is in error since wstring::length returns number of characters, not
numberof 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
holdthe 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: Igor Korot
Date:
Subject: libpq bug?
Next
From: Mitar
Date:
Subject: In which session context is a trigger run?