Re: strange output on openbsd C code

2007-03-20 Thread Otto Moerbeek
On Mon, 19 Mar 2007, Matthew R. Dempsky wrote:

 On Mon, Mar 19, 2007 at 09:55:04PM -0400, Paul D. Ouderkirk wrote:
  And because I love to reply to myself, if I compile it with -O3, I can
  reproduce your results:
 
 -O3 enables -fstrict-aliasing, which this program violates.  The man
 page explains in more detail.

Yep, it's a bit sad to see all the attempts at explaining the bug. But
this one hits the mark.

Additionally, while stock gcc enables -fstrict-aliasing with -O2, on
OpenBSD -fstrict-aliasing is not enabled with -O2, since experience
shows violations of pointer aliasing rules are seen a lot in the wild.

See man gcc-local:

-   The -O2 option does not include -fstrict-aliasing, as this option
causes issues on some legacy code.  -fstrict-aliasing is very unsafe
with code that plays tricks with casts, bypassing the already weak
type system of C.

So don't play tricks like that unless you really understand the issues
involved. 

-Otto



Re: strange output on openbsd C code

2007-03-20 Thread Stuart Henderson
On 2007/03/19 19:12, Gustavo Rios wrote:
 I am writing a very simple program but the output change for the c
 variable value change every time i run it.

It doesn't do this on any system I've tried it on -

i386, amd64:

x:8589934593
0,1:1,2
c:2

sparc64:

x:8589934593
0,1:2,1
c:2



Re: strange output on openbsd C code

2007-03-19 Thread Nick !

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:

I am writing a very simple program but the output change for the c
variable value change every time i run it. What would it be my mistake
on the source? Did i forget some thing?

#include stdio.h

int
main(int argc, char **argv)
{
unsigned long long  x, c;
unsigned*p;


^ this is bad. always say your types in full.



x = 1, x+= (unsigned long long)1  33 ;


This sets *(x) to 1, and then sets *(x) (yes, the same one) to 1+(133)


p = (void *)x;
c = p[0] * p[1];


That is, p[1] == *(x+1) is never getting set to anything. Thus the
reason the output is always changing is because p[1] is always
pointing at a different, random location in memory that has some
previous value.

Further, p[1] is not your memory, and it's only by chance that you're
not segfaulting.


fprintf(stdout, x:%llu\n, x);
fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
fprintf(stdout, c:%llu\n, c);

return 0;
}




-Nick



Re: strange output on openbsd C code

2007-03-19 Thread Gustavo Rios

So, why when i printf p[1], it correctly prints 2?

On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
 I am writing a very simple program but the output change for the c
 variable value change every time i run it. What would it be my mistake
 on the source? Did i forget some thing?

 #include stdio.h

 int
 main(int argc, char **argv)
 {
 unsigned long long  x, c;
 unsigned*p;

^ this is bad. always say your types in full.


 x = 1, x+= (unsigned long long)1  33 ;

This sets *(x) to 1, and then sets *(x) (yes, the same one) to 1+(133)

 p = (void *)x;
 c = p[0] * p[1];

That is, p[1] == *(x+1) is never getting set to anything. Thus the
reason the output is always changing is because p[1] is always
pointing at a different, random location in memory that has some
previous value.

Further, p[1] is not your memory, and it's only by chance that you're
not segfaulting.

 fprintf(stdout, x:%llu\n, x);
 fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
 fprintf(stdout, c:%llu\n, c);

 return 0;
 }



-Nick




Re: strange output on openbsd C code

2007-03-19 Thread Nick !

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:


On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:
 On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
  I am writing a very simple program but the output change for the c
  variable value change every time i run it. What would it be my mistake
  on the source? Did i forget some thing?
 
  #include stdio.h
 
  int
  main(int argc, char **argv)
  {
  unsigned long long  x, c;
  unsigned*p;

 ^ this is bad. always say your types in full.

 
  x = 1, x+= (unsigned long long)1  33 ;

 This sets *(x) to 1, and then sets *(x) (yes, the same one) to 1+(133)

  p = (void *)x;
  c = p[0] * p[1];

 That is, p[1] == *(x+1) is never getting set to anything. Thus the
 reason the output is always changing is because p[1] is always
 pointing at a different, random location in memory that has some
 previous value.

 Further, p[1] is not your memory, and it's only by chance that you're
 not segfaulting.

  fprintf(stdout, x:%llu\n, x);
  fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
  fprintf(stdout, c:%llu\n, c);
 
  return 0;
  }
 
So, why when i printf p[1], it correctly prints 2?


Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
is the first byte of those 8, and p[1] is the second, and due to
coincidence and twos-complement encoding it happens to show you the
expected numbers. Maybe?

But that doesn't explain why the output is always changing.

Wait, how is * defined on two voids? That shouldn't even compile
(unless it's autocasting to int?).

-Nick



Re: strange output on openbsd C code

2007-03-19 Thread Frank Denis

Le Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios ecrivait :

I am writing a very simple program but the output change for the c
variable value change every time i run it.
int
main(int argc, char **argv)
{
   unsigned long long  x, c;
   unsigned*p;
   p = (void *)x;
   fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);


 p is the address of x. That address is not supposed to be anything fixed.


--
Frank Denis - j [at] pureftpd.org - My geeky blog: http://00f.net



Re: strange output on openbsd C code

2007-03-19 Thread Gustavo Rios

No!

p sizeof is 4 bytes, p is the frst byt of x, and p + 1 is the 4th
byte. Casting is only on attribution of x to p.

Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
Not a random value.

On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:

 On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:
  On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
   I am writing a very simple program but the output change for the c
   variable value change every time i run it. What would it be my mistake
   on the source? Did i forget some thing?
  
   #include stdio.h
  
   int
   main(int argc, char **argv)
   {
   unsigned long long  x, c;
   unsigned*p;
 
  ^ this is bad. always say your types in full.
 
  
   x = 1, x+= (unsigned long long)1  33 ;
 
  This sets *(x) to 1, and then sets *(x) (yes, the same one) to 1+(133)
 
   p = (void *)x;
   c = p[0] * p[1];
 
  That is, p[1] == *(x+1) is never getting set to anything. Thus the
  reason the output is always changing is because p[1] is always
  pointing at a different, random location in memory that has some
  previous value.
 
  Further, p[1] is not your memory, and it's only by chance that you're
  not segfaulting.
 
   fprintf(stdout, x:%llu\n, x);
   fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
   fprintf(stdout, c:%llu\n, c);
  
   return 0;
   }
  
 So, why when i printf p[1], it correctly prints 2?

Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
is the first byte of those 8, and p[1] is the second, and due to
coincidence and twos-complement encoding it happens to show you the
expected numbers. Maybe?

But that doesn't explain why the output is always changing.

Wait, how is * defined on two voids? That shouldn't even compile
(unless it's autocasting to int?).

-Nick




Re: strange output on openbsd C code

2007-03-19 Thread David Higgs

Whenever a printf fixes everything, it's usually because that forces
gcc to put the values on the stack.  Without the printf, they're
probably in registers and p points to who knows what.

If you grok assembly, try objdump on the executable to see what's
going on.  If you want to multiply the two halves of a long long, I'd
suggest shifting and masking it out explicitly instead of using
pointer tricks like this.

--david

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:

No!

p sizeof is 4 bytes, p is the frst byt of x, and p + 1 is the 4th
byte. Casting is only on attribution of x to p.

Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
Not a random value.

On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:
 On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
 
  On 3/19/07, Nick ! [EMAIL PROTECTED] wrote:
   On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
I am writing a very simple program but the output change for the c
variable value change every time i run it. What would it be my mistake
on the source? Did i forget some thing?
   
#include stdio.h
   
int
main(int argc, char **argv)
{
unsigned long long  x, c;
unsigned*p;
  
   ^ this is bad. always say your types in full.
  
   
x = 1, x+= (unsigned long long)1  33 ;
  
   This sets *(x) to 1, and then sets *(x) (yes, the same one) to 1+(133)
  
p = (void *)x;
c = p[0] * p[1];
  
   That is, p[1] == *(x+1) is never getting set to anything. Thus the
   reason the output is always changing is because p[1] is always
   pointing at a different, random location in memory that has some
   previous value.
  
   Further, p[1] is not your memory, and it's only by chance that you're
   not segfaulting.
  
fprintf(stdout, x:%llu\n, x);
fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
fprintf(stdout, c:%llu\n, c);
   
return 0;
}
   
  So, why when i printf p[1], it correctly prints 2?

 Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
 doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
 is the first byte of those 8, and p[1] is the second, and due to
 coincidence and twos-complement encoding it happens to show you the
 expected numbers. Maybe?

 But that doesn't explain why the output is always changing.

 Wait, how is * defined on two voids? That shouldn't even compile
 (unless it's autocasting to int?).

 -Nick




Re: strange output on openbsd C code

2007-03-19 Thread Paul D. Ouderkirk

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:

No!

p sizeof is 4 bytes, p is the frst byt of x, and p + 1 is the 4th
byte. Casting is only on attribution of x to p.

Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
Not a random value.


For what it's worth, when I run this code I always get the same
(presumably correct) values:

[EMAIL PROTECTED]:~ $ ./a.out
x:8589934593
0,1:1,2
c:2

[EMAIL PROTECTED]:~ $ uname -rm
4.0 i386

--
--
Paul D. Ouderkirk
Senior UNIX System Administrator
JadedPixel Technologies
[EMAIL PROTECTED]
--
laughing,
in the mechanism
-- William Gibson



Re: strange output on openbsd C code

2007-03-19 Thread Paul D. Ouderkirk

On 3/19/07, Paul D. Ouderkirk [EMAIL PROTECTED] wrote:

On 3/19/07, Gustavo Rios [EMAIL PROTECTED] wrote:
 No!

 p sizeof is 4 bytes, p is the frst byt of x, and p + 1 is the 4th
 byte. Casting is only on attribution of x to p.

 Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
 problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
 Not a random value.

For what it's worth, when I run this code I always get the same
(presumably correct) values:



And because I love to reply to myself, if I compile it with -O3, I can
reproduce your results:

[EMAIL PROTECTED]:~ $ cc -O3 test.c
[EMAIL PROTECTED]:~ $ ./a.out
x:8589934593
0,1:1,2
c:1387628864   (value of c changes with every execution)

--
--
Paul D. Ouderkirk
Senior UNIX System Administrator
JadedPixel Technologies
[EMAIL PROTECTED]
--
laughing,
in the mechanism
-- William Gibson



Re: strange output on openbsd C code

2007-03-19 Thread Matthew R. Dempsky
On Mon, Mar 19, 2007 at 08:02:10PM -0400, Nick ! wrote:
 Wait, how is * defined on two voids? That shouldn't even compile
 (unless it's autocasting to int?).

``unsigned'' is short for ``unsigned int''.  The ``(void *)'' cast is
a red herring.



Re: strange output on openbsd C code

2007-03-19 Thread Matthew R. Dempsky
On Tue, Mar 20, 2007 at 01:35:28AM +0100, Frank Denis wrote:
 Le Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios ecrivait :
 I am writing a very simple program but the output change for the c
 variable value change every time i run it.
 int
 main(int argc, char **argv)
 {
unsigned long long  x, c;
unsigned*p;
p = (void *)x;
fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
 
  p is the address of x. That address is not supposed to be anything fixed.  

He never prints p.



Re: strange output on openbsd C code

2007-03-19 Thread Darrin Chandler
On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:
 I am writing a very simple program but the output change for the c
 variable value change every time i run it. What would it be my mistake
 on the source? Did i forget some thing?
 
 #include stdio.h
 
 int
 main(int argc, char **argv)
 {
unsigned long long  x, c;
unsigned*p;
 
x = 1, x+= (unsigned long long)1  33 ;
p = (void *)x;
c = p[0] * p[1];
 
fprintf(stdout, x:%llu\n, x);
fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
fprintf(stdout, c:%llu\n, c);
 
return 0;
 }

I run this many times, with other stuff in between, and I always get:

$ ./gustavo 
x:8589934593
0,1:1,2
c:2

Same values for everything, every time. Hmm.

-- 
Darrin Chandler   |  Phoenix BSD Users Group
[EMAIL PROTECTED]  |  http://bsd.phoenix.az.us/
http://www.stilyagin.com/darrin/  |



Re: strange output on openbsd C code

2007-03-19 Thread a . velichinsky
On Mon, Mar 19, 2007 at 07:17:46PM -0700, Darrin Chandler wrote:
 On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:
  I am writing a very simple program but the output change for the c
  variable value change every time i run it. What would it be my mistake
  on the source? Did i forget some thing?
  
  #include stdio.h
  
  int
  main(int argc, char **argv)
  {
 unsigned long long  x, c;
 unsigned*p;
  
 x = 1, x+= (unsigned long long)1  33 ;
 p = (void *)x;
 c = p[0] * p[1];
  
 fprintf(stdout, x:%llu\n, x);
 fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
 fprintf(stdout, c:%llu\n, c);
  
 return 0;
  }
 
 I run this many times, with other stuff in between, and I always get:
 
 $ ./gustavo 
 x:8589934593
 0,1:1,2
 c:2
 
 Same values for everything, every time. Hmm.

Compile it with -O3. Then enjoy.



Re: strange output on openbsd C code

2007-03-19 Thread Adam
Gustavo Rios [EMAIL PROTECTED] wrote:

 I am writing a very simple program but the output change for the c
 variable value change every time i run it. What would it be my mistake
 on the source? Did i forget some thing?

Bleh, what a depressing thread.  Gustavo, why didn't you bother to
provide all the relevant info, like that you are foolishly compiling
with -O3?  Its pretty well known that gcc doesn't always produce correct
output when using optimizations more aggressive than -O2.  Stop using
-O3 and suddenly it prints 2 all the time.  Looks like this bug is
fixed in gcc 4.2 at least.

And what is with the answers being provided guys?  Its only 8 lines,
and its not that hard to follow.  Guessing random answers isn't
usually very helpful, maybe reading it and saying there's nothing
wrong with that code, are you using compiler optimizations? would
work better.  At least a few people tried it instead of making up
non-existant bugs in the code.

Adam



Re: strange output on openbsd C code

2007-03-19 Thread Darrin Chandler
On Tue, Mar 20, 2007 at 04:40:08AM +0200, [EMAIL PROTECTED] wrote:
 Compile it with -O3. Then enjoy.

Sure. Then I'll light my hair on fire and put it out with a ballpeen
hammer.

-- 
Darrin Chandler   |  Phoenix BSD Users Group
[EMAIL PROTECTED]  |  http://bsd.phoenix.az.us/
http://www.stilyagin.com/darrin/  |



Re: strange output on openbsd C code

2007-03-19 Thread Matthew R. Dempsky
On Mon, Mar 19, 2007 at 09:55:04PM -0400, Paul D. Ouderkirk wrote:
 And because I love to reply to myself, if I compile it with -O3, I can
 reproduce your results:

-O3 enables -fstrict-aliasing, which this program violates.  The man
page explains in more detail.



Re: strange output on openbsd C code

2007-03-19 Thread Tobias Ulmer
On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:
 I am writing a very simple program but the output change for the c
 variable value change every time i run it. What would it be my mistake
 on the source? Did i forget some thing?
 
 #include stdio.h
 
 int
 main(int argc, char **argv)
 {
unsigned long long  x, c;
unsigned*p;

/* stop abusing the comma operator */
x = 1, x+= (unsigned long long)1  33 ;
/* Fine, storing random void * pointers in p is allowd */
p = (void *)x;
/*
 * You assume that the in memory representation of an
 * unsigned [2] looks exactly like unsigned long long and you
 * expect to access the valid initialized memory of x by
 * dereferencing p.
 *
 * These assumptions are all wrong.
 */
c = p[0] * p[1];
 
fprintf(stdout, x:%llu\n, x);
fprintf(stdout, 0,1:%u,%u\n, p[0], p[1]);
fprintf(stdout, c:%llu\n, c);
 
return 0;
 }
 


Your program is invalid. Gcc has all rights to fuck it up,
-omg-optimized or not.

Casts are basically syntactic sugar for (i know what i'm doing, now
shut up and stop complaining). Remove the (void *) and compile with
-Wall.

Tobias



Re: strange output on openbsd C code

2007-03-19 Thread Woodchuck
On Tue, 20 Mar 2007, Tobias Ulmer wrote:

 

 /*
  * You assume that the in memory representation of an
  * unsigned [2] looks exactly like unsigned long long and you
  * expect to access the valid initialized memory of x by
  * dereferencing p.
  *
  * These assumptions are all wrong.
  */

 

Indeed.

The error is very similar to making assumptions about how
the internal structure of x, p and c might relate in the
commonly seen:

union roach_motel {
unsigned long long x;
unsigned int p[2];
unsigned char c[8];
} foo;  /* draws bugs */

We haven't even scratched the surface of the subtle joys of
big-endian addressing schemes (note the plural) or alignment
requirements in some architectures.

 Your program is invalid. Gcc has all rights to fuck it up,
 -omg-optimized or not.

It's not strictly invalid, it just doesn't follow the programmer's
intent.  This is the most difficult sort of bug to find for the
original programmer (code blindness), but a stranger can find it
more easily.  Now if we take code like the example program, and
intersperse a few thousand lines of other code, and break it all
up over a hundred functions (and files, and bury the declarations
about 5 deep in include files), put half the bug in a library, we
have the makings of a Windoze-grade nightmare. Add some conditionals,
we can write it so that the problem with uninitialized c only
shows up one run in a thousand.  0xDEADBEEF comes to mind...

 Casts are basically syntactic sugar for (i know what i'm doing, now
 shut up and stop complaining). Remove the (void *) and compile with
 -Wall.

Some casts are READ MY MIND, DAMN IT!.  In this case, we notice
that cc -O2 and cc -O3 have different psychic skills.

I murmur again about alignment issues, which don't exist for
the i386 architecture, as far as I know, except as an optimization.
(And certain obscure features of the PeeCee like DMA.)

The C standard is full of references to alignment. 
In some architectures, I believe   
void *p,*q;  p=(long *)1;  q=(char *)1;  
p==q will be false.

To the OP:  you can't do both bit-wise manipulation and arithmetic
and expect the results to be always what you think.  Besides endian
issues and alignment issues, there can be questions of arithmetic
(2s-complement, 1s-complement, and others).  The PeeCee has blinded
many to the rich diversity of hardware possibilities.

Sometimes you just have to drag out the assembler.

Dave
-- 
 Resistance is futile.  You've already been assembled.