Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Discussion of open issues, suggestions and bugs regarding UniDAC (Universal Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
SMM
Posts: 9
Joined: Mon 15 Jul 2013 23:02

Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by SMM » Sat 29 Apr 2017 14:04

Hi There

I see that Unidac 7.0.1 is supposed to support Linux. When I run the very simple code below i get:
First chance exception at $000000000045F2A3. Exception class EEncodingError with message 'Character index out of bounds (0)'. Process testunidac (1918)
What am I doing wrong? Must be me, the Unidac team wouldn't release something this fundamentally broken. I have looked for Linux specific docs, there appear to be none...

App code.

Code: Select all

program testunidac;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Uni,
  UniProvider,
  PostgreSQLUniProvider;

var
  Conn : TUniConnection;

begin
  Conn := TUniConnection.Create(nil);
  try
    Conn.LoginPrompt := false;
    Conn.Server := 'myserver';
    Conn.Database := 'mydatabase';
    Conn.Username := 'myuser';
    Conn.Password := 'mypassword';
    Conn.ProviderName := 'PostgreSQL';
    Conn.Connect;
    WriteLn('Connected');
    ReadLn;
    Conn.Disconnect;
    Conn.Free;
  except
    on E: Exception do
      begin
        Writeln(E.ClassName, ': ', E.Message);
        Conn.Free;
      end;
  end;
end.

ertank
Posts: 172
Joined: Wed 13 Jan 2016 16:00

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by ertank » Sun 30 Apr 2017 11:52

Hi,

I do not know if below is the solution to your case. I suggest you set TUniConnection.Provider the first thing after a create. Also, not to leak any memory, you should wrap your Conn variable in try..finally block.

You can try something like:

Code: Select all

program testunidac;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Uni,
  UniProvider,
  PostgreSQLUniProvider;

var
  Conn : TUniConnection;

begin
  Conn := TUniConnection.Create(nil);
  try
    Conn.ProviderName := 'PostgreSQL';    
    Conn.LoginPrompt := False;
    Conn.Server := 'myserver';
    Conn.Database := 'mydatabase';
    Conn.Username := 'myuser';
    Conn.Password := 'mypassword';
    try
      Conn.Connect();
    except
      on E: Exception do
      begin
        Writeln(E.ClassName, ': ', E.Message);
        Exit();
      end;
    end;

    if Conn.Connected then 
      WriteLn('Connected')
    else
      WriteLn('No connection cound be established');
    ReadLn();
    Conn.Disconnect();
  finally
    Conn.Free();
  end;
end.

SMM
Posts: 9
Joined: Mon 15 Jul 2013 23:02

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by SMM » Sun 30 Apr 2017 16:37

Thank you, but moving the connection provider does not work. This is what it looks like now (I have tried it without the specificoptions, and with them, and with each specific option alone). The code builds under Win32 and Win64.

I have subsequently tried building a SQLite version of this connection test and it works, so the fault must lie in the Provider itself. Anyone from the UNIDac team here?

Also, thanks for the code advice, but this was just made really simple for clarity.

Code: Select all

uses
  System.SysUtils,
  Uni,
  UniProvider,
  PostgreSQLUniProvider;

var
  Conn : TUniConnection;

begin
  Conn := TUniConnection.Create(nil);
  try
    Conn.LoginPrompt := false;
    Conn.ProviderName := 'PostgreSQL';
    Conn.SpecificOptions.Values['PostgreSQL.UseUnicode'] := 'True';
    Conn.SpecificOptions.Values['PostgreSQL.Charset'] := 'utf-8';
    Conn.Server := 'myserver';
    Conn.Database := 'mydatabase';
    Conn.Username := 'myuser';
    Conn.Password := 'mypassword';
    Conn.Connect;
    WriteLn('Connected');
    ReadLn;
    Conn.Disconnect;
    Conn.Free;
  except
    on E: Exception do
      begin
        Writeln(E.ClassName, ': ', E.Message);
        Conn.Free;
      end;
  end;
end.

SMM
Posts: 9
Joined: Mon 15 Jul 2013 23:02

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by SMM » Sun 30 Apr 2017 19:05

I am furious. Am I the only poor sod that uses Unidac with Postgres and tried to run it under Linux? Clearly Devart did no testing on the Postgres Provider. This is unforgivable for a company that happily takes my money, and it is not an insignificant sum. It states clearly in the release sticky:

"Linux in RAD Studio 10.2 Tokyo is supported"

It is now clear to me the Postgres provider was not tested. Luckily I own the source code. So after a uninstall and reinstall of my Delphi installation on two machines, and messing about with the connection parameters for hours, I decide to install Unidac from source too see what is going on (still thinking the error is mine). I eventually get to an error in the password hashing bit of the connection. Linux has one based strings boys. (If anyone from the Unidac team actually reads this - the error is on Line 1442 of PgSQLProtocolUni.pas, or of the MD5.ToString in CLRClasses.pas, or in IdeVer.inc, depending on your point of view).

What is clear, it that the PotgreSQL provider was never tested (or if it was, the tests are superficial and useless). I recognise that we all write bugs, all the time. Of course we do. That is human. This was sloppiness to try push out a Linux version quickly. Bad bad practices Devart. Shocking.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by ViktorV » Thu 04 May 2017 09:16

Unfortunately, we could not reproduce the problem on the latest UniDAC 7.0.1 version. When running the provided samples we did not get the specified errors.
Perhaps, in the application where the error is reproduced, you are using some other Database, Username or Password values (which contain national characters).
Please specify:
- whether you are using national characters (not Latin) in the values of the Database, Username or Password properties;
- specify the exact version of PostgreSQL server
- specify the values of the lc_messages, lc_ctype и lc_collate parameters in the PostgreSQL server settings.
To receive a faster reply, please compose a full sample demonstrating the specified behavior and send it to us using the contact form https://www.devart.com/company/contactform.html, including scripts for creating and filling database objects.

SMM
Posts: 9
Joined: Mon 15 Jul 2013 23:02

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by SMM » Thu 04 May 2017 15:13

Victor, two things;

1. I did submit a report, I have contact from your team about it.

2. I simply don't see how it is possible that it is working for you. It WILL work under Lazarus, it WILL NOT work with Tokyo. The example I sent is the one I am running. If you read the second post I made in the thread, you will see that line 1442 in PgSQLProtocolUni.pas is at issue.

Code: Select all

Encoding.Default.GetBytes(MD5str.ToString, 0, MD5str.Length, UserWithSalt, 0);
Encoding.Default fetches System.Sysutils TUTF8Encoding class. Under Linux Tokyo, strings are 1 based. So calling GetBytes with the above signature gives you a character index out of bounds exception, all day every day. Essentially you are telling me that the following code

Code: Select all

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  Buff : TBytes;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    SetLength(Buff, 8);
    TEncoding.UTF8.GetBytes('A string', 0, 8, Buff, 0);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Compiles and runs on YOUR version of Delphi Tokyo but not mine. It can't. Strings on Delphi Tokyo are 1 based. If you cange that to TEncoding.UTF8.GetBytes('A string', 1, 8, Buff, 0) it will work. The same in your code. As I said. I compiled your library with the change to line 1442 of of PgSQLProtocolUni.pas and everything works (I own the source code - as I have said)

Code: Select all

Encoding.Default.GetBytes(MD5str.ToString, 1, MD5str.Length, UserWithSalt, 0);
- but it will no longer work under Lazarus. Lazarus string handling <> Delphi Tokyo string handling, and PgSQLProtocolUni.pas only checks it runs under Linux. This error MUST surface under Tokyo.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by ViktorV » Thu 04 May 2017 16:28

Thank you for the information. We have reproduced the problem and it will be fixed in the next build.

SMM
Posts: 9
Joined: Mon 15 Jul 2013 23:02

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by SMM » Fri 05 May 2017 00:26

Again, this is very worrying for me. It clearly implies that AT LEAST the Postgres provider was not tested under Delphi Tokyo, an IDE Devart claimed to support for the release. One would think that you would have a suite of tests to run against the code, and if you do, they are fundamentally broken.

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Linux support - Exception class EEncodingError with message 'Character index out of bounds (0)'

Post by ViktorV » Wed 24 May 2017 13:35

The new build of UniDAC 7.0.2 including this fix is already available for download.

Post Reply