Page 1 of 1
Structure Bug,Invalid memory access.
Posted: Mon Nov 21, 2016 12:40 pm
by diskay
PureBasic 5.50 (Windows - x86)
Code: Select all
Structure s1
a.i
b.i
EndStructure
Structure s2
c.s1
d.i
EndStructure
Structure s3
e.i
f.s2[0]
EndStructure
Procedure.i test()
Define t1.s1
Define t3.s3
t3\f[0]\c = t1
ProcedureReturn 1
EndProcedure
Debug test()
[ERROR] Invalid memory access. (read error at address 0)
Code: Select all
Structure s1
a.i
b.i
EndStructure
Structure s2
c.s1
d.i
EndStructure
Structure s3
e.i
f.s2[0]
EndStructure
Procedure.i test()
Define t3.s3
Define t1.s1
t3\f[0]\c = t1
ProcedureReturn 1
EndProcedure
Debug test()
OK!
Re: Structure Bug,Invalid memory access.
Posted: Mon Nov 21, 2016 8:42 pm
by Demivec
This doesn't reserve any memory for data in the structure. It is a static array and the dimension should be the number of elements + 1.
PureBasic Help wrote:Please note, that in structures a static array[] doesn't behave like the normal BASIC array (defined using Dim) to be conform to the C/C++ structure format (to allow direct API structure porting). This means that a[2] will allocate an array from 0 to 1 where Dim a(2) will allocate an array from 0 to 2.
This tries to assign something to unreserved memory, as was pointed out with the earlier structure definition of the field containing the static array. A zero index would be permitted here if the static array had had at least one element.
Declaring a structural static array with a dimension size of zero has a use with structured pointers that are used to access the memory of a structured array of varying lengths. When used this way it will allow any index value to be used without a debugger check. The pointer still needs to point to memory that has been reserved for the array.
You sidestepped the IMA in your second example by luck because you were overwriting memory set aside for another variable (you reversed the order of the declared variables).
By changing your procedure you can see that it is accessing the memory of the other variable because they follow each other in memory:
Code: Select all
Procedure.i test()
Define t3.s3
Define t1.s1
t1\a = 12
;t3\f[0]\c = t1
Debug t3\f[0]\c\a
ProcedureReturn 1
EndProcedure
Not a bug.
If you need a single element inside the static array it can be correctled like this:
Code: Select all
Structure s1
a.i
b.i
EndStructure
Structure s2
c.s1
d.i
EndStructure
Structure s3
e.i
f.s2[1] ; <==change
EndStructure
Procedure.i test()
Define t1.s1
Define t3.s3
t3\f[0]\c = t1
ProcedureReturn 1
EndProcedure
Debug test()
Re: Structure Bug,Invalid memory access.
Posted: Tue Nov 22, 2016 6:46 am
by diskay
Demivec ,Thank you.
I see:
Code: Select all
Structure TOKEN_PRIVILEGES
PrivilegeCount.l
Privileges.LUID_AND_ATTRIBUTES[0]
EndStructure
PureBasic 5.50 (Windows - x86)
Re: Structure Bug,Invalid memory access.
Posted: Tue Nov 22, 2016 7:41 am
by Demivec
diskay: I'm not sure what you understood from what I shared so I'
llsisam2@aol.com just comment on what you'very shared.
I see Microsoft'Security description of this structure:
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
Members
PrivilegeCount: This must be set to the number of entries in the Privileges array.
Privileges: Specifies an array of LUID_AND_ATTRIBUTES structures. Each structure contains the LUID and attributes of a privilege. To get the name of the privilege associated with a LUID, call the LookupPrivilegeName function, passing the address of the LUID as the value of the lpLuid parameter.
Important The constant ANYSIZE_ARRAY is defined as 1 in the public header Winnt.h. To create this array with more than one element, you must allocate sufficient memory for the structure to take into account additional elements.
This indicates that the minimum size of the Privileges array is 1 and that the array needs more memory allocated if it is larger than the minimum size. Neither of those things are addressed by the structure definition you showed me. That structure is designed with a certain use in mind and that use would include certain restrictions. One of those restrictions would be that you can not determine the total size of the structure by using SizeOf(TOKEN_PRIVILEGES)..
Did you have a specific question?
Re: Structure Bug,Invalid memory access.
Posted: Wed Nov 30, 2016 11:53 am
by Cyllceaux
It is a Bug...
// Ungültiger Speicherzugriff. (Schreibfehler an der Adresse 0)
Code: Select all
Procedure.i test()
Define t1.s1
Define t3.s3
t3\f[0]\c = t1
ProcedureReturn 1 ;<--- BAM
EndProcedure
//OK
Code: Select all
Procedure.i test()
Define t3.s3
Define t1.s1
t3\f[0]\c = t1
ProcedureReturn 1
EndProcedure
I you swap the "Define"-Block, it run different.
Re: Structure Bug,Invalid memory access.
Posted: Wed Nov 30, 2016 4:34 pm
by Fred
It's not a but you are reading from not allocated area.
Re: Structure Bug,Invalid memory access.
Posted: Wed Nov 30, 2016 6:53 pm
by diskay
PureBasic 5.50 (x86)
Structure Viewer :
Code: Select all
Structure TOKEN_PRIVILEGES
PrivilegeCount.l
Privileges.LUID_AND_ATTRIBUTES[0]
EndStructure
msdn:
Code: Select all
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; //ANYSIZE_ARRAY=1
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
Re: Structure Bug,Invalid memory access.
Posted: Wed Nov 30, 2016 7:02 pm
by User_Russian
https://msdn.microsoft.com/us-en/librar ... s.85).aspx Important The constant ANYSIZE_ARRAY is defined as 1 in the public header Winnt.h. To create this array with more than one element, you must allocate sufficient memory for the structure to take into account additional elements.
Re: Structure Bug,Invalid memory access.
Posted: Wed Nov 30, 2016 7:38 pm
by DarkDragon
Cyllceaux wrote:It is a Bug...
// Ungültiger Speicherzugriff. (Schreibfehler an der Adresse 0)
Code: Select all
Procedure.i test()
Define t1.s1
Define t3.s3
t3\f[0]\c = t1
ProcedureReturn 1 ;<--- BAM
EndProcedure
//OK
Code: Select all
Procedure.i test()
Define t3.s3
Define t1.s1
t3\f[0]\c = t1
ProcedureReturn 1
EndProcedure
I you swap the "Define"-Block, it run different.
Just imagine your situation as if you're accessing t1 via t3\f[0] if you swap the order. In reality, everything is a bit more complicated. You have to reserve enough memory for your structured variable. Otherwise you'll always access invalid memory or memory reserved for other variables with t3\f[0]. But this is intentional, otherwise you couldn't use all of the WinAPI.
I assume you're German:
Stell dir das am besten so vor, dass du im zweiten Fall mit vertauschter Reihenfolge mit t3\f[0] dann auf t1 zugreifst. In wahrheit ist es noch komplizierter. Du musst erstmal genügend speicher für die strukturierte Variable reservieren. Sonst greifst du mit t3\f[0] immer auf ungültigen Speicher zu oder auf Speicher der anderen Variablen gilt. Das ist aber Absicht, denn sonst wäre nicht die ganze WinAPI verwendbar.
Re: Structure Bug,Invalid memory access.
Posted: Thu Dec 01, 2016 2:50 am
by nco2k
as of the [0/1] problem, it should be fixed in the upcoming version of pb:
http://purebasic.fr/english/viewtopic.php?f=4&t=66442
however, this does not solve your problem of simply using this structure the wrong way.
here is what you have to do:
- call the appropriate function to find out the required size.
- create a structured buffer of given size.
- call the appropriate function again to fill the buffer.
- browse through the buffer to get the information you need.
this code uses TOKEN_GROUPS instead of TOKEN_PRIVILEGES, but the concept of use is the same:
Code: Select all
EnableExplicit
Define hToken, dwSize, *GroupInfo.TOKEN_GROUPS, SIDAuth.SID_IDENTIFIER_AUTHORITY\Value[5] = 5, *SID, i, Result$
If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY, @hToken) And hToken
SetLastError_(0)
If GetTokenInformation_(hToken, #TokenGroups, 0, 0, @dwSize) = #False And GetLastError_() = #ERROR_INSUFFICIENT_BUFFER And dwSize
*GroupInfo = AllocateMemory(dwSize)
If *GroupInfo
If GetTokenInformation_(hToken, #TokenGroups, *GroupInfo, dwSize, @dwSize)
If AllocateAndInitializeSid_(@SIDAuth, 2, #SECURITY_BUILTIN_DOMAIN_RID, #DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, @*SID)
For i = 0 To *GroupInfo\GroupCount - 1
If EqualSid_(*GroupInfo\Groups[i]\Sid, *SID)
Result$ = "OK"
Break
EndIf
Next
FreeSid_(*SID)
EndIf
EndIf
FreeMemory(*GroupInfo)
EndIf
EndIf
CloseHandle_(hToken)
EndIf
Debug Result$
and as you can see, it doesnt crash.
c ya,
nco2k