[unixODBC-dev] Bug ? SQLGetDiagFieldW() assume buffer lengths in SQLWCHAR instead of bytes

Nick Gorham nick.gorham at easysoft.com
Fri Jan 13 18:26:40 GMT 2006


Marc Herbert wrote:

>According to article ID 294169 from Microsoft
> <http://support.microsoft.com/default.aspx?scid=kb;EN-US;q294169>
>SQLGetDiagFieldW() should always assume sizes are in bytes. The
>rationale goes like this: "some returned values are strings, but other
>are not, so let's standardize on bytes." Check the article for more.
>
>I think I spotted a bug where unixodbc assumes some sizes are in SQLW
>characters instead of bytes, see attached patch to see where is
>located the issue.
>
>The bug is by chance not very harmful: it ends up _under_estimating
>the size of the buffer given by the user, and returning a size twice
>too big.
>
>This patch is untested, consider it as a pointer to the relevant part
>of the code and a suggestion only.
>
>This bug probably occurs at other similar places.
>  
>

Thanks,

I could be wrong, but the code you mentioned is in the Ansi entry point 
SQLGetDiagField, and its used when the driver only has the unicode entry 
point. So the driver is allocating a buffer thats big enough to handle 
the ansi buffer in unicode, so it then can convert it back to ansi on 
return.

I agree with you however on the length thats passed into the driver 
being wrong,

But maybe this is correct:

        if ( __get_connection( head ) -> unicode_driver &&
            CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
        {
            SQLRETURN ret;
            SQLWCHAR *s1 = NULL;
            int char_buffer_len = sizeof( SQLWCHAR ) * buffer_length ;

            if ( buffer_length > 0 )
            {
                s1 = malloc(char_buffer_len + sizeof( SQLWCHAR ) );
            }

            ret = SQLGETDIAGFIELDW( __get_connection( head ),
                    head -> handle_type,
                    __get_driver_handle( head ),
                    rec_number,
                    diag_identifier,
                    s1 ? s1 : diag_info_ptr,
                    char_buffer_len,
                    string_length_ptr );

            if ( SQL_SUCCEEDED( ret ) && s1 && diag_info_ptr )
            {
                unicode_to_ansi_copy( diag_info_ptr, s1, SQL_NTS, 
__get_connection( head ));
            }

            if ( s1 )
            {
                free( s1 );
            }

            if ( string_length_ptr && *string_length_ptr > 0 )
            {
                *string_length_ptr /= sizeof( SQLWCHAR );
            }

What do you think?

-- 
Nick Gorham
Easysoft Limited



More information about the unixODBC-dev mailing list