Menu

#652 TZRowAccessor.CopyBuffer missing NIL pointer check

7.2.14
open
nobody
ZDbcCache (1)
Bug Report
2026-06-04
2026-05-31
MmVisual
No

The line is without NIL pointer check:
PIZLob(@DestBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ := PIZLob(@SrcBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^.Clone

I have change this to:
for i := 0 to FHighLobCols do
if (SrcBuffer^.Columns[FColumnOffsets[FLobCols[i]]] = bIsNotNull) then begin
PPointer(@DestBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ := nil; //init to avoid refcounting
if PIZLob(@SrcBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ <> nil then begin
if CloneLobs
then PIZLob(@DestBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ := PIZLob(@SrcBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^.Clone
else PIZLob(@DestBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ := PIZLob(@SrcBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^;
end;
end;

Now, it works fine.
In attachmet the fixed file.

1 Attachments

Discussion

  • marsupilami79

    marsupilami79 - 2026-06-02

    Hello Markus,

    how do you trigger that bug by normal use of Zeos?

    Best regards,

    Jan

     
  • MmVisual

    MmVisual - 2026-06-02
    If qBestellUseLief12.AsInteger <> i Then
    Begin
      if not (qBestell.State in [dsEdit, dsInsert]) then
        qBestell.Edit;
      qBestellUseLief12.AsInteger := i;
    End;
    : : :
    qBestell.Post;
    

    I've had this bug for many years. It only appears every few months and is probably related to SQLite. When it happens, you can no longer save the data record; you have to abort, close the EXE, restart it, and then enter the same information again. Then, suddenly, you can save the input. The underlying code isn't anything special, just a normal TZQuery with a few fields. The SQL query contains some JOINs, which, of course, aren't saved. The code itself works, but this problem occurs every few weeks. Presumably, Zeos has a problem somewhere else where this memory isn't correctly allocated, but I'm circumventing it by checking for NIL. I haven't noticed any negative side effects; all the data is stored in the database, even though nothing is copied when the data is NIL. I don't really understand it. There are other parts of this function that aren't executed when the data is NIL, so I thought that this NIL check was simply omitted.

     
    • marsupilami79

      marsupilami79 - 2026-06-04

      I don't really understand it. There are other parts of this function that aren't executed when the data is NIL, so I thought that this NIL check was simply omitted.

      Hello Markus, thet is what I tried to find out - if the bug is possibly caused by another bug somewhere else. Usually Egonhugeist had a kinda contract in mind that some Values had to be filled in - no matter what.
      Anyway - since the bug seems to be hard to reproduce, I applied the patch. Also please think about migrating to Zeos 8. I doubt that there will be another Zoes 7.2 release - simply because I don't have the time to do a full release.

      Best regards,

      Jan

       
    • marsupilami79

      marsupilami79 - 2026-06-04

      Hello Markus,

      after reading the code once more, I can understand why there was no check for nil there: The following line is meant to check, if the blob has contents:

      if (SrcBuffer^.Columns[FColumnOffsets[FLobCols[i]]] = bIsNotNull)
      

      So -> if there is contents, why should the pointer to the contents be nil? So I guess what could trigger the problem. Maybe you have a chance to verify it.
      If for some reason a blob field in the database contains an empty string (''), then it would not be null, but we also could not assign a pointer for data, because trying to do a GetMem with zero (0) length (GetMem(BlobContents, 0)) most probably will return a nil pointer.
      Could you try to test that scenario? Will it lead to the access violation that you had?

      Best regards,

      Jan

       
  • MmVisual

    MmVisual - 2026-06-04

    Hi Jan,
    Thank you very much for looking into my issue.

    This line isn’t enough:

    if (SrcBuffer^.Columns[FColumnOffsets[FLobCols[i]]] = bIsNotNull)
    

    Only after adding this did I stop getting exceptions; I tested it:

    if PIZLob(@SrcBuffer.Columns[FColumnOffsets[FLobCols[i]]+1])^ <> nil
    

    The index with “+1” doesn’t contain any data that can be cast to PIZLob(), so “Clone” can’t be executed. The line that checks “bIsNotNull” does not look at the index + 1.

    Regarding Zeos V7: The license terms state that if I modify Zeos code, I must return these changes to the community; therefore, I am submitting a bug report with my changes.
    It’s perfectly fine with me if you don’t release updates for the old V7. Anyone who wants to continue using Zeos V7 and happens to have this bug as well can use my code from the bug report here.
    However, this is worth noting for you—it might be a bug that could also cause issues in Zeos V8.
    And I like held do things better ;-)

    Regarding Zeos V8: In my program, I use a lot of ReadOnly fields that can only be written to by the EXE itself, but never by the user. Unfortunately, Zeos V8 no longer wants to write these RO fields to the DB. (ZDbcGenericResolver.pas line 762 ( Metadata.IsReadOnly(I) or ) )

    Best regards,

    Markus

     

Log in to post a comment.

Auth0 Logo