Patch, Version 4: Problem solved

Anders Norlander
Tue May 4 10:36:00 GMT 1999

Corinna Vinschen wrote:
>The sizes and offsets of the structures TOKEN_PRIVILEGES and
>LUID_AND_ATTRIBUTES are different between the old and the new defines:

>typedef struct _LUID_AND_ATTRIBUTES {
>        LUID   Luid;                           offset 0, size 8
>        DWORD  Attributes;                     offset 8, size 4
>} LUID_AND_ATTRIBUTES;                                   size 16!!!

>This happens, because of the new definition of LARGE_INTEGER, which is
>the base type for LUID. It now contains a union member of type
>LONGLONG (8 Bytes):
>So gcc alignes the LUID type to a 8 byte boundary, instead of a
>4 byte boundary.
>For testing purposes, I have made the "LONGLONG QuadPart" to a comment
>and now, AdjustTokenPrivileges() works as expected.

I investigated this and come up with a minimal testcase and sent
it to egcs-bugs. I've attached the bug report below.

>So I like to suggest, to erase the definition of QuadPart in the
>definitions of LARGE_INTEGER and ULARGE_INTEGER in include/winnt.h,
>until the alignment problem is solved. The fix is following.
>Moreover, I have attached a tiny fix to my security patch, which
>solves a "permission denied" problem, if you set file permissions
>to e.g. "chmod 000 foo".
It is also possible to solve by using the packed attribute. Perhaps
that is better?

Report sent to egcs-bugs:
Consider the code below (on egcs 1.1.1 ix86 platforms):
#include <stdio.h>

/* get member offset */
#define ofs(t,f) ((int)&(((t*)0)->f))

typedef struct {
        int a;
        int b;
} A;

typedef struct {
  A a;
  int i;
} B;

int main()
  B b;
  printf("B: %d\n.a: %d, %d\n.i: %d, %d\n", sizeof(B),
         sizeof(b.a), ofs(B,a),
         sizeof(b.i), ofs(B,i));
  return 0;

When running the compiled program you get
B: 12
.a: 8, 0
.i: 4, 8

Now change the defintion of A to
typedef struct {
        double d; /* or long long */
} A;

now you get
B: 16  <-- why?
.u: 8, 0
.i: 4, 8

For some subtle reason egcs aligns B on a 16 byte
boundary, the alignment of A is not changed but the alignment
of B which has a member of type A. This, however, only happens
when you put an eight bytes large numeric type in A. So even no
sizes have changed, alignment has.
Is this a (mis)feature or perhaps an off-by-one error in egcs?
Using gcc 2.7.3 you get the expected results.


More information about the Cygwin-developers mailing list