Structure Bug,Invalid memory access.

Just starting out? Need help? Post your questions and find answers here.
diskay
User
User
Posts: 25
Joined: Sun Aug 02, 2015 7:17 pm

Structure Bug,Invalid memory access.

Post 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!
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Structure Bug,Invalid memory access.

Post by Demivec »

Code: Select all

f.s2[0]
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.

Code: Select all

t3\f[0]\c = t1
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()
diskay
User
User
Posts: 25
Joined: Sun Aug 02, 2015 7:17 pm

Re: Structure Bug,Invalid memory access.

Post 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)
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Structure Bug,Invalid memory access.

Post 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?
Cyllceaux
Enthusiast
Enthusiast
Posts: 510
Joined: Mon Jun 23, 2014 1:18 pm

Re: Structure Bug,Invalid memory access.

Post 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.
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Structure Bug,Invalid memory access.

Post by Fred »

It's not a but you are reading from not allocated area.
diskay
User
User
Posts: 25
Joined: Sun Aug 02, 2015 7:17 pm

Re: Structure Bug,Invalid memory access.

Post 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;
User_Russian
Addict
Addict
Posts: 1518
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: Structure Bug,Invalid memory access.

Post 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.
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Structure Bug,Invalid memory access.

Post 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.
bye,
Daniel
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Structure Bug,Invalid memory access.

Post 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
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
Post Reply