#1 2013-12-07 02:58:54

ncook
Member
From: Australia
Registered: 2013-08-13
Posts: 19

Assertion failure in mORMot.pas with an empty string field

Hi Arnaud.
Sorry, but I have to report that I'm getting an error "Assertion failure in mORMot.pas line 16841".

Here's my minimal code to reproduce the error...

type
  TSQLNullTest1 = class(TSQLRecord)
  private
    fText: RawUTF8;
    fMemo: RawUTF8;
  published
    property fldText: RawUTF8 index 255 read fText write fText;
    property fldMemo: RawUTF8 read fMemo write fMemo;
  end;

procedure TfrmMORMmot_Dev_Main.btnNullTest1Click(Sender: TObject);
const
  c_DbFileExtension = '.mdb';
var
  DbFileSpec: string;
  Conn: TOleDBConnectionProperties;
  Model: TSQLModel;
  Client: TSQLRestClientDB;
  Obj: TSQLNullTest1;
begin
  DbFileSpec := ChangeFileExt(application.ExeName, c_DbFileExtension);
  Conn := TOleDBJetConnectionProperties.Create(DbFileSpec, '', '', '');
  //Conn := TOleDBMSSQL2008ConnectionProperties.Create(c_SQLTest_ServerName, c_SQLTest_DatabaseName, c_SQLTest_UserName, c_SQLTest_Password);
  try
    Model := TSQLModel.Create([TSQLNullTest1]);
    try
      VirtualTableExternalRegister(Model, TSQLNullTest1, Conn, 'tblNullTest1');

      Client := TSQLRestClientDB.Create(Model, nil, '', TSQLRestServerDB);
      try
        Client.Server.CreateMissingTables;

        Obj := TSQLNullTest1.Create;
        try
          Obj.fldText := '';
          Obj.fldMemo := '';

          Client.Add(Obj, True);
        finally
          Obj.Free;
        end;
      finally
        Client.Free;
      end;
    finally
      Model.Free;
    end;
  finally
    Conn.Free;
  end;
end;

The line causing the error is in mORMot.pas, near the bottom of routine TJSONObjectDecoder.EncodeAsSQLPrepared

assert(P-pointer(tmp)<length(tmp));

My first thought as that the test was had an edge condition bug, and maybe it should be using "<=" rather than "<", but I was wrong.
I found this was not the problem once I added the second RawUTF8 to the TSQLNullTest1 type (originally I only had a single text field in the sample code). With two empty string fields, P is now pointing beyond the end of tmp, so using "<=" does not fix the problem.

Rather it appears that the problem is actually related to the following line near the top of the routine

SetLength(tmp,FieldLen+2*FieldCount+12); // max length

where FieldLen seems to be too low, and so it is making tmp slightly too short.

I guess there are a few possible ways to fix this (e.g. changing the calculation of FieldLen, or changing the calculation of the length of tmp), but I expect there could be side effects if it is not fixed properly, so I'll have to leave it to you to work out what the "correct" fix is.

If it makes any difference, I am using a Jet database (TOleDBJetConnectionProperties), but as you can see in the sample code, I have also tried this with an MS SQL database (TOleDBMSSQL2008ConnectionProperties), and I got the same result.

I have a another problem with the same test code, but I'll put that on a separate topic shortly, as it is unrelated to this error.

Offline

#2 2013-12-07 14:18:56

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Assertion failure in mORMot.pas with an empty string field

There was indeed an issue!

I've fixed a potential buffer overflow in TJSONObjectDecoder.EncodeAsSQLPrepared().
See http://synopse.info/fossil/info/79f5becba8

Thanks for the feedback.

Offline

#3 2013-12-08 22:07:17

ncook
Member
From: Australia
Registered: 2013-08-13
Posts: 19

Re: Assertion failure in mORMot.pas with an empty string field

Thanks Arnaud.
That has fixed the problem.

Offline

Board footer

Powered by FluxBB