Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
#pragma pack(1) is the devil

 
Post new topic   Reply to topic Printable version
 View previous topic  Having problems with "Hello World... Post :: Post NTFS to FAT32 converter?  View next topic  
Author Message
Bak
?ls -s
0 in


Age:24
Gender:Gender:Male
Joined: Jun 11 2004
Posts: 1826
Location: USA
Offline

PostPosted: Thu Jul 13, 2006 4:58 am    Post subject: #pragma pack(1) is the devil Reply to topic Reply with quote

Okay.... so I spent many hours debugging this bug, two entire coding sessions today. I'm pretty sure it's the most elusive bug I've found my coding career. Here's how it goes, three files main.cpp, header.h, and impl.cpp:

main.cpp:
Code: Show/Hide
#include <stdio.h>

#pragma pack(1)
#include "header.h"

void func()
{
   SampleStruct pm;

   printf("main, sizeof SampleStruct = %i\n",sizeof(SampleStruct));
}

int main()
{
   func();

   return 0;
}


header.h:
Code: Show/Hide
struct SampleStruct
{
   bool bool1;
   
   __int64 int1;

   SampleStruct();
};


impl.cpp:
Code: Show/Hide
#include "header.h"

#include <stdio.h>

SampleStruct::SampleStruct()
{
   int1 = bool1 = 0;

   printf("myplayer.cpp, sizeof struct = %i\n",sizeof(SampleStruct));
}


Seems innocent enough right? Well there's a buffer overflow in there, and if you run it, the code will crash when the execution leaves func() (assuming you have the same compiler and computer and compiler options as me). Here's the reason: Both main.cpp and impl.cpp use the SampleStruct. main uses #pragma pack(1), so it gives the struct exactly the number of bytes needed for the structure. In func(), only this number of bytes is reserved on the stack for variable pm.

In the constructor, which is in impl.cpp, the #pragma pack(1) is never seen so it pads the structure with extra space. Then when it writes values to the variables, it assumes they are packed. When main.cpp invokes the constructor, there is no padding on the stack. Bam, the constructor writes to memory that's not reserved for the structure, possibly overwriting the stack pointer, buffer overflow.

This bug is a bitch to track down as the compiler pads variables all the time, so overwriting a buffer a little bit might go unnoticed. For example if I change __int64 (a 64 bit variable on my computer) to an int (a 32 bit variable on my computer), the program executes fine. However, it prints out the different sizeof()'s for the same structure and you can see they are different. I compiled this using VS.NET2003.

So what the fuck? When you're using #pragma pack, make sure you push and pop the settings within the same file every time. Never leave an open ended pragma pack in a file, or include files within a pragma pack'd section of code. Anything less and you're asking to shoot yourself in the foot.

so in the standard asss distribution, defs.h include an open ended #pragma pack(1)... which leeches into everything that does an #include "asss.h" (every module). I think gcc by default ignores #pragma pack's, could this be the cause of some of asss' windows version instability (vs linux version)? I know it would be a bitch to trace if it was...
_________________
SubSpace Discretion: A Third Generation SubSpace Client
Back to top
View users profile Send private message Add User to Ignore List AIM Address
Cyan~Fire
I'll count you!
I'll count you!


Age:36
Gender:Gender:Male
Joined: Jul 14 2003
Posts: 4608
Location: A Dream
Offline

PostPosted: Thu Jul 13, 2006 11:23 am    Post subject: Reply to topic Reply with quote

True, it's confusing, but it does make sense to me.

The simple solution is just to #pragma pack(push, 1) at the beginning of every include that needs it and #pragma pack(pop) at the end. I don't see what the big deal is.
_________________
This help is informational only. No representation is made or warranty given as to its content. User assumes all risk of use. Cyan~Fire assumes no responsibility for any loss or delay resulting from such use.
Wise men STILL seek Him.
Back to top
View users profile Send private message Add User to Ignore List Visit posters website
Bak
?ls -s
0 in


Age:24
Gender:Gender:Male
Joined: Jun 11 2004
Posts: 1826
Location: USA
Offline

PostPosted: Thu Jul 13, 2006 3:23 pm    Post subject: Reply to topic Reply with quote

Still might have #includes in the middle that use it.
Back to top
View users profile Send private message Add User to Ignore List AIM Address
Cyan~Fire
I'll count you!
I'll count you!


Age:36
Gender:Gender:Male
Joined: Jul 14 2003
Posts: 4608
Location: A Dream
Offline

PostPosted: Fri Jul 14, 2006 12:02 am    Post subject: Reply to topic Reply with quote

As long as every file uses push and pop correctly, it should never be a problem.
Back to top
View users profile Send private message Add User to Ignore List Visit posters website
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> Non-Subspace Related Coding All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 688 page(s) served in previous 5 minutes.

phpBB Created this page in 0.540894 seconds : 29 queries executed (83.6%): GZIP compression disabled