Bug 146082 - In Basic , Structures stored in an array
Summary: In Basic , Structures stored in an array
Status: NEW
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: BASIC (show other bugs)
Version:
(earliest affected)
7.1.2.2 release
Hardware: All All
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-12-06 18:42 UTC by Andrew Pitonyak
Modified: 2022-07-28 12:20 UTC (History)
6 users (show)

See Also:
Crash report or crash signature:


Attachments
Screenshots showing the results (441.95 KB, application/vnd.oasis.opendocument.graphics)
2021-12-06 21:15 UTC, Rafael Lima
Details
Simple code showing 1 aspect of bug (9.68 KB, application/vnd.oasis.opendocument.spreadsheet)
2021-12-22 04:09 UTC, Leslie
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pitonyak 2021-12-06 18:42:15 UTC
I found a bug in LibreOffice 7.2.2.2 on Fedora Linux as supplied by Fedora and Windows 7.1.2.2. Next I installed 7.2.4.1 for Windows and tested it again with the same results.

I was asked by Wolfgang Jäger jag@psilosoph.de about a bug he found in LibreOffice related structures stored in Arrays in Basic. I have verified that there is a bug, but I wanted feedback before I file the bug report and I have NOT at this point looked at the code. 

I expect a Structure to copy by value, which it seems to do, but a structure in an array does NOT act as expected. It is even worse for user defined data types. The details are complicated, but, if an array of structures does this: 

a(1) = a(2)

It might act like the value copied and it might not (depending on the circumstances and how the array was declared). 

This bug was originally noted with a user defined type so I wrote a test using a built-in UNO Struct com.sun.star.awt.Point

Test using User type “PersonType”

Type PersonType
  FirstName As String
  LastName As String
End Type

Sub PrintPersons(s, x)
  Print "Expect (" & s & ") found (" & x.FirstName & " " & x.LastName & ")"
End Sub

Sub PrintPoint(s, x)
  Print "Expect " & s & " Found (" & x.X & ", " & x.Y & ")"
End Sub

This is the original disturbing code. Attempting to copy an element from the array causes problems. The same when trying to assign back into to the array. 


Sub otherExampleCreateNewType
REM Producing very strange errors. 
REM Inspect the two array elements and h at the same time
REM down to the inside variables while executing lines 19 through 21 stepwise. 

Dim Person(1 To 2) As PersonType
Person(1).FirstName = "Andrew"
Person(1).LastName = "Pitonyak"
Person(2).FirstName = "Funny"
Person(2).LastName = "Lupp"

PrintPersons("Andrew", Person(1)) ' Andrew (correct)
PrintPersons("Funny", Person(2)) ' Funny (correct)

Dim h As PersonType
h = Person(1)
Person(1) = Person(2)
Person(2) = h
PrintPersons("Funny", Person(1)) ' Andrew (wrong)
PrintPersons("Andrew", Person(2)) ' Funny (wrong)

REM Now look at the prints, and frown.
Dim h1 As PersonType, h2 As PersonType
h1 = Person(1)
h2 = Person(2)
PrintPersons("Funny", h1) ' Funny (correct)
PrintPersons("Andrew", h2) ' Funny (wrong)

End Sub

Next I run this using a built-in UNO type and have exactly the same incorrect behaviors
Sub otherExampleCreateAWTPoint

Dim p(1 To 2) As New com.sun.star.awt.Point
p(1).X = 1
p(1).Y = 2
p(2).X = 3
p(2).Y = 4

PrintPoint("(1, 2)", p(1)) ' Correct
PrintPoint("(3, 4)", p(2)) ' Correct

Dim h As New com.sun.star.awt.Point
h = p(1)
p(1) = p(2)
p(2) = h
PrintPoint("(3, 4)", p(1)) ' wrong
PrintPoint("(1, 2)", p(2)) ' wrong

REM Now look at the prints, and frown.
Dim h1 As New com.sun.star.awt.Point, h2 As New com.sun.star.awt.Point
h1 = p(1)
h2 = p(2)
PrintPoint("(3, 4)", h1)  ' Correct
PrintPoint("(1, 2)", h2)  ' Wrong

End Sub

I then changed how the array is declared as shown below and this fixed the problematic

Dim p(1 To 2) As Object
p(1) = CreateUnoStruct( "com.sun.star.awt.Point" )
p(2) = CreateUnoStruct( "com.sun.star.awt.Point" )

Doing the same for the PersonType also causes it to work as expected:

Dim Person(1 To 2) As Object
Person(1) = CreateObject("PersonType")
Person(2) = CreateObject("PersonType")

It gets worse. If I modify the subroutine to always make a copy of the object and then use the object that is passed to the subroutine, then suddenly the first program works for points, but the same fix does not work when done for PersonType.

Sub PrintPoint(s, y)
  Dim x
  x = y
  Print "Expect " & s & " Found (" & x.X & ", " & x.Y & ")"
End Sub

Clearly something is wrong / inconsistent.
Comment 1 Rafael Lima 2021-12-06 21:15:48 UTC
Created attachment 176747 [details]
Screenshots showing the results

There's definitely a problem here. I ran Andrew's code and got many issues, however a bit different than originally reported.

For instance, in "otherExampleCreateNewType" (the sub with PersonType objects), I got weird results in a piece of the code before the one with the comment. It seems the error started earlier. See in the attached file (Page 1) that the values being watched do not match the values being printed (Person(1) and Person(2) have the same values).

Now about the "otherExampleCreateAWTPoint" (the sub with Point objects), on Page 2 the values watched do make sense, but the ones printed are wrong (as pointed out by Andrew). However, note that there is a difference with how the watch behaved in each example.

Still on "otherExampleCreateAWTPoint" I got a different behavior than originally reported. I got the correct outputs in the last 2 prints, instead of a Correct and a Wrong one. Notice that the watched values are also correct (see Page 3).

System info:
Version: 7.2.3.2 / LibreOffice Community
Build ID: 20(Build:2)
CPU threads: 16; OS: Linux 5.13; UI render: default; VCL: kf5 (cairo+xcb)
Locale: pt-BR (pt_BR.UTF-8); UI: en-US
Ubuntu package version: 1:7.2.3~rc2-0ubuntu0.21.10.1~lo1
Calc: threaded
Comment 2 Rafael Lima 2021-12-06 21:17:55 UTC
Andreas, maybe this bug would interest you.
Comment 3 Leslie 2021-12-22 04:08:11 UTC
I have added an attachment which shows 1 aspect of this bug in much simpler code.      
2 simple integer classes and a collector class.  
Both the simple integer classes look like this: 

private _a as integer 

private sub class_initialize() 
end sub 
private sub class_terminate() 
end sub 

And the collector like this: 

public _a() as object 'ClassA
public _c() as ClassC
private _upperBound as integer

private sub class_initialize() 
   _upperBound = -1
end sub 
private sub class_terminate() 
end sub 
public sub AddElements(byref elementA as ClassA, byref elementC as ClassC)
   _upperBound = _upperBound + 1
   redim preserve _a(0 to _upperBound)
   set _a(_upperBound) = elementA
   redim preserve _c(0 to _upperBound)
   set _c(_upperBound) = elementC
   msgbox(_a(0)._a) 
   msgbox(_c(0)._c)
end sub
 
And then a test to see what happens: 
public sub test() 
   dim n as integer 
   dim a as ClassA, b as ClassB, c as ClassC, d as ClassD

   set a = new ClassA 
   a._a = 10
   set c = new ClassC 
   c._c = 12
		
   set b = new ClassB
   b.AddElements(a,c)
end sub 

When in the above code _a() is defined as ClassA the message box will always show 0. 
When it is defined as object it will show the expected result 10.
Comment 4 Leslie 2021-12-22 04:09:21 UTC
Created attachment 177076 [details]
Simple code showing 1 aspect of bug
Comment 5 Julien Nabet 2022-02-19 11:00:09 UTC
Mike: thought you might be interested in this one or at least have some opinion here.
Comment 6 Mike Kaganski 2022-02-19 18:59:46 UTC
(In reply to Julien Nabet from comment #5)

We have some utter mess with by-reference handling of array elements in general (and not only in array - but it needs case-by-case analysis). We already were hit several time in different forms (including some strange behavior with ReDim); but first of all, I would love to see (or develop) some formal specification where the ByRef semantics are needed - which array operations? Assignment of array to another variable - do they become pointers to the same array? or are different arrays with pointers to same elements? or different arrays with independent elements? Passing to ByVal function argument? ReDim? Here I suppose Andrew is the greatest expert who could at least suggest a list of cases to consider, with suggested expected semantics ... and then test all variations of element types -s strings, numbers, UNO and user types, VBA-specific like enums... and then see the matrix of problems - and then try to revise the implementation to fix that. Because now I feel that trying to fix this thing would not help, only resulting in regression because of not seeing the whole picture.

(Anyway, my opinion with this bug is that whenever the author of the bug is Andrew, we must just automatically confirm :D - there's no one more knowledgeable in this matter on this planet.)
Comment 7 Vladimir Sokolinskiy 2022-05-19 14:18:42 UTC
Let's first look at issues related to arrays of UNO structures.

If the function PrintPoint is written like this:

Sub PrintPoint(s, Byval x)
  Print "Expect " & s & " Found (" & x.X & ", " & x.Y & ")"
End Sub

then everything is displayed correctly in function otherExampleCreateAWTPoint.


Another problematic macro on the same topic.

Sub TestAWTPoint
  Dim p(0) As New com.sun.star.awt.Point
  Dim h As New com.sun.star.awt.Point
  h.X=1
  p(0) = h
  Msgbox p(0).X   ' 0 : Wrong
  h=Nothing
  h=p(0)
  Msgbox h.X      ' 1 : Correct
End Sub

Maybe this code will be useful for making a diagnosis.