public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/45249]  New: Indirect variable parameters sometimes cause segmentation fault
@ 2010-08-10 21:55 rogerio at rilhas dot com
  2010-08-10 22:03 ` [Bug c++/45249] " rogerio at rilhas dot com
                   ` (57 more replies)
  0 siblings, 58 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 21:55 UTC (permalink / raw)
  To: gcc-bugs

When using variable parameters indirectly (the variable-parameter function
calls another function to format its parameters giving it the original address
of the format string), the results are usually ok for non-optimized builds and
cause segmentation faults in optimized builds.

In a large project I also detected that unoptimized builds would cause
segmentation faults if the variable-parameter function declared a char buffer,
and would not fail if it declared an int buffer of the same total size. However
this is difficult to reproduce, so the test case I send you does not show this.

In the code I send you you can see "main" calling "format_direct" to format
some variable parameters, which in turn calls "format_indirect" to do the
actual work. This is a pattern I use a lot and for which I never had a problem
under Windows with any of Microsoft's Visual Studio versions (I'm fairly new to
LINUX, this is my first software port project).

If this test case is compiled with "g++ -v -save-temps
gcc_bug_format_indirect.cpp -o gcc_bug_format_indirect.exe.ok" then it works
ok, but if it is compiled with "g++ -v -save-temps -O2
gcc_bug_format_indirect.cpp -o gcc_bug_format_indirect.exe.ko" it causes a
segmentation fault (at least on my system it does, when it doesn't cause a
segmentation fault the results are just wrong).

I attach the preprocessed file, the source file, and the compilation script I
used.


-- 
           Summary: Indirect variable parameters sometimes cause
                    segmentation fault
           Product: gcc
           Version: 4.3.3
            Status: UNCONFIRMED
          Severity: blocker
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: rogerio at rilhas dot com
 GCC build triplet: i686-virtualboxvm-ubuntu?
  GCC host triplet: i686-virtualboxvm-ubuntu?
GCC target triplet: i686-virtualboxvm-ubuntu?


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
@ 2010-08-10 22:03 ` rogerio at rilhas dot com
  2010-08-10 22:04 ` rogerio at rilhas dot com
                   ` (56 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 22:03 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #1 from rogerio at rilhas dot com  2010-08-10 22:03 -------
Created an attachment (id=21448)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21448&action=view)
Preprocessed file


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
  2010-08-10 22:03 ` [Bug c++/45249] " rogerio at rilhas dot com
  2010-08-10 22:04 ` rogerio at rilhas dot com
@ 2010-08-10 22:04 ` rogerio at rilhas dot com
  2010-08-10 22:07 ` pinskia at gcc dot gnu dot org
                   ` (54 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 22:04 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #2 from rogerio at rilhas dot com  2010-08-10 22:03 -------
Created an attachment (id=21449)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21449&action=view)
Source file with comments


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
  2010-08-10 22:03 ` [Bug c++/45249] " rogerio at rilhas dot com
@ 2010-08-10 22:04 ` rogerio at rilhas dot com
  2010-08-10 22:04 ` rogerio at rilhas dot com
                   ` (55 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 22:04 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #3 from rogerio at rilhas dot com  2010-08-10 22:04 -------
Created an attachment (id=21450)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21450&action=view)
Compilation script (for the working and non-working builds)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (2 preceding siblings ...)
  2010-08-10 22:04 ` rogerio at rilhas dot com
@ 2010-08-10 22:07 ` pinskia at gcc dot gnu dot org
  2010-08-10 22:33 ` rogerio at rilhas dot com
                   ` (53 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-10 22:07 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #4 from pinskia at gcc dot gnu dot org  2010-08-10 22:07 -------
This code will never work as you are not using va_start/va_end to access the
arguments.  For format_indirect you should just pass around a va_list instead.


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (3 preceding siblings ...)
  2010-08-10 22:07 ` pinskia at gcc dot gnu dot org
@ 2010-08-10 22:33 ` rogerio at rilhas dot com
  2010-08-10 22:36 ` rogerio at rilhas dot com
                   ` (52 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 22:33 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #5 from rogerio at rilhas dot com  2010-08-10 22:33 -------
Are you sure this is the way to resolve this issue? I think this will make GCC
an inferior product, as all other compilers I've tested produce correct
results. As GCC sometimes produces correct code (and in such cases it works) I
don't see anyway to get around the fact that this is, in fact, a bug.

Additionally, I've sent you an example of how to compile it in a way that it
works when compiled with GCC. Furthermore, I think most people would expect it
to work as I'm passing the address of the original parameter. I've also shown
the code for Windows where I can then use a va, but there doesn't seem to exist
an equivalent for LINUX. Even if there were an equivalent this bug would affect
its behaviour too, as I've checked the memory contents and the format string
seems to have been copied and its original address on the stack is no longer
preserved, which, of course, is wrong.

If you still decide to discard this problem I will end up with no way to work
around it and will have to definitively abandon LINUX as a software platform
because of this shortcomming of GCC (which, I repeat, is not found on other
compilers).

Thanks,
Rogerio


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (4 preceding siblings ...)
  2010-08-10 22:33 ` rogerio at rilhas dot com
@ 2010-08-10 22:36 ` rogerio at rilhas dot com
  2010-08-10 23:08 ` pinskia at gcc dot gnu dot org
                   ` (51 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-10 22:36 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #6 from rogerio at rilhas dot com  2010-08-10 22:35 -------
Let me just add: if you can tell me what options to set to make it always work
that would already be helpful. I noticed that disabling optimizations helps,
but not everytime (adding a lot of local automatic variables to the direct
function seems to have a negative effect sometimes).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (5 preceding siblings ...)
  2010-08-10 22:36 ` rogerio at rilhas dot com
@ 2010-08-10 23:08 ` pinskia at gcc dot gnu dot org
  2010-08-11  0:55 ` rogerio at rilhas dot com
                   ` (50 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-10 23:08 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #7 from pinskia at gcc dot gnu dot org  2010-08-10 23:08 -------
>correct results. 

There is no correct results since you are depending on undefined behavior.  It
is not a short coming of GCC but rather the source you are trying to port.  The
code is not portable at all.  It will not work on other compilers besides GCC. 
It will not work on other targets where MS had a compiler (like their PowerPC
Windows machines [xbox and WinNT 3.5 and such]).


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (6 preceding siblings ...)
  2010-08-10 23:08 ` pinskia at gcc dot gnu dot org
@ 2010-08-11  0:55 ` rogerio at rilhas dot com
  2010-08-11  0:58 ` pinskia at gcc dot gnu dot org
                   ` (49 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11  0:55 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #8 from rogerio at rilhas dot com  2010-08-11 00:54 -------
I think you are wrong, I'm not depending on undefined behaviour. When I request
&format that is clearly defined: I should be getting the address of the format
pointer as placed on the stack. Just like I would when requesting the address
of an int parameter placed on the stack, I would get its stack address. If were
to write to that address I would write onto the stack. That is well defined.
Then, by another well defined attribute (the calling convention) I should be
able to navigate the stack to get the other parameters. There is no hack here!
It is all well defined. As long as the compiler doesn't "mess it up" and do
something "undocummented" or something that violates these well-defined
behaviours then everything is just fine. A compiler that doesn't verify both of
these 2 well-defined characteristics simultaneously has a bug.

I'm not coding for the Xbox nor for NT 3.5, but I assume that if I can get
Microsoft's compiler to use the calling convention that I want I will be able
to get the code to run. The reasoning is very simple: when I request
Microsoft's compilers something like &format I get the stack address for the
format variable placed on the stack (as expected, not some copy unpredictably
placed somewhere else on the stack), and as Microsoft's compilers strictly
respect the calling conventions then I'm sure it would work. Microsoft's
compilers don't "mess it up" while optimizing. The only possibility for it not
to work would be for Microsoft's compiler not to let me select the calling
convention I wanted, which I seriously doubt.

To prove this I just compiled the code to Windows Mobile and it works just fine
on an ARM platform (my mobile phone), compiled with Visual Studio 2008, despite
the fact that it is a very diferent platform from x86. In fact, it is
conceptually very close to PowerPC, so I think this code would compile
correctly on PowerPC as well.

As I stated there is no undefined behaviour here, and I know exactly what I am
doing when I'm navigating the stack based on the address of the original format
string on the stack and on the calling convention used. That is what I would do
if programming in assembly language, so the compiler must not "mess up" these 2
well defined items.

So there is nothing wrong with my source, and it works everywhere I tried
except with GCC. From your comment I suspect I'm just wasting my time, because
you seem to be missing the point altogether. But of course I respect your
position of not fixing this (as I must, since I'm not the one working on
GCC!!).

I reopened the bug just to give you this last piece of information about the
Windows Mobile (no need to reply if you don't want to). Since you are very keen
on closing this report whithout backing your claims and clearly explaining how
come you say the behaviour is not defined I don't feel the interest to persue
this issue any further (especially because I feel it shouldn't be necessary for
me to explain all this, I think it should be fairly obvious to people
developing a compiler), so I will just drop LINUX for now (until I have the
oportunity to test other compilers).

Thanks for your attention anyway!


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (7 preceding siblings ...)
  2010-08-11  0:55 ` rogerio at rilhas dot com
@ 2010-08-11  0:58 ` pinskia at gcc dot gnu dot org
  2010-08-11  1:57 ` rogerio at rilhas dot com
                   ` (48 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11  0:58 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #9 from pinskia at gcc dot gnu dot org  2010-08-11 00:58 -------
>Then, by another well defined attribute (the calling convention) I should be
able to navigate the stack to get the other parameters.

No, the C/C++ standard says doing that is undefined because the array size is
1.  That is the point I am trying to make, you are depending on undefined
behavior as defined by the C/C++ standards.  Going past the bounds of an array
is undefined.  This is well known that it causes undefined behavior.  Yes
&argument is defined but it is defined only be accessed to that address no
others.


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (8 preceding siblings ...)
  2010-08-11  0:58 ` pinskia at gcc dot gnu dot org
@ 2010-08-11  1:57 ` rogerio at rilhas dot com
  2010-08-11  3:52 ` pinskia at gcc dot gnu dot org
                   ` (47 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11  1:57 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #10 from rogerio at rilhas dot com  2010-08-11 01:57 -------
I'm replying now not in the context of the bug (since as I mentioned I must
move on), but just as a conversation between 2 persons. So please don't getting
me wrong for insisting.

The cdecl calling convention on x86-32 machines says that for any function call
the arguments are placed on the stack as a series of 4-byte pushed values. I've
checked that GCC respects this convention when calling a function and not
optimized. So, for a typical GCC functiona call GCC pushes the parameters
correctly according to the cdecl calling convention:

func(a, b, c, d)

... the parameters will pushed right-to-left like:

push d (4-byte)
push c (4-byte)
push b (4-byte)
push a (4-byte)
call func

Obviously there are exceptions for doubles and structs, but this is not the
case here as char* and int are pushed exactly the same way, as 4-byte values.
This is well defined, right? The cdecl calling convention defines this clearly,
correct? Or does GCC somehow uses another calling convention?

Another thing well-defined in C is that when I request the address of a
variable I get the address of it. So, inside func, when I request &a I get the
stack address where "a" was pushed to. This is also well defined, right?

Another thing well defined in C is what happens when navigating an array out of
its bounds. Unlinke what you say, the behaviour is deterministic in absolutely
every machine: if my PTR4 pointer to a 4-byte value contains the value X, then
PTR4[1] accesses address memory X+4. The same way, if my PTR2 points to a
2-byte value at address Y, then PTR2[1] will access address Y+2. There is no
hack here either, the behaviour is very well defined, and C doesn't care about
or check the bounds of the array.

So, if the calling convention states (in the example above) that "b" is placed
4 bytes after "a", and that "c" is placed 4 bytes after "b", and so on, it
follows, without any doubt, that if I get a PTR4 to point to "a", and the
address of "a" on the stack is X, then PTR4[0] accesses "a", PTR4[1] accesses
"b", PTR4[2] accesses "c", and so on. It doesn't mater the size of the array, C
will not check nor care about it, I can navigate the stack with it. That is
what I do with format_address, since it is a char** and char** has size 4 then
format_address is a PTR4. So, format_address[0] is "a" (or it should be if
&format returned the true address of "a"), and *without any doubt or hack*
format_address[1] is "b", and *with exactly the same confidence*,
format_address[2] is "c", and so on. This is one of the most well established
bases in C, for several decades now, so there is really no arguing about it.

The problem is that GCC, when optimizing, places "a" somewhere on the stack
which is not contiguous to "b". I think (although I'm not sure) that GCC does
something like this:

push d
push c
push b
push a
call format_direct

format_direct:
push some varied stuff
push [a copy of the original "a" again somewhere]
push [address of the above copy of "a"]
call format_indirect

format_indirect: (example)
mov eax,[address of the copy of "a"+0] // not the original "a", but the copy
mov ebx,[address of the copy of "a"+4] // contains some varied stuff, not "b"

I'm not sure if GCC does exactly this, but I'm sure that, when optimizing, GCC
does not place "a" adjacent to "b", and it should. Since I cannot get to "b"
I'm not sure if the same happens to "c".

This clearly violates the calling convention. If the calling convention were
respected then "a", "b", "c", and "d" would all be adjacent, so I could
navigate the 1-entry (4-byte) array using format_address[0], format_address[1],
format_address[2], and format_address[3]. I don't see how you can refute one of
the most well established properties of C, as the language allows me to
populate any memory buffer with whichever stuff and then navigate with a 4-byte
pointer (as long as properly aligned, which is the case here). I'm just doing
that with the stack, wich should be (by the calling convention) a 4-byte
aligned memory buffer with 4 adjacent 4-byte values "abcd".

So, my point is: if - req1) GCC placed the parameters on the stack adjacent to
one another (as it should as a result of the selected calling convention) *AND*
- req2) if it gave me the address of the original format parameter on the stack
(as it should by the definition of getting the address of a function parameter)
then the code would work correctly, since - req3) is well established that C
does not perform array boundary checking and, thus, PTR4[1] accesses memory
location exactly 4 bytes after memory location PTR4[0].

Since I believe none of these 3 requirements is refutable, and since they are
all well established, then - bug1) GCC is not putting the parameters adjacent
on the stack as it should *OR* - bug2) GCC is not giving me the correct address
when I ask for &format. The - bug3) of not doing pointer arithmetic correctly
because the array has size 1 (your argument) is simply not true, I checked it
while debugging, and I've seen it to be correct on the most varied machines
(from PIC microcontrollers to PC's and mobile phones), otherwise it will not be
C. The only thing that is allowed to vary (for performance reasons) is the is
parameter width, as microcontrollers PIC16 have 1-byte parameters, PIC24 has
2-byte parameters, and x86-32 has 4 byte parameters).

Another interpretation of your comment of "array of size 1" would be to think
that a char* would take up more or less than 4 bytes, resulting in something
like:

option a:
push32 d
push32 c
push32 b
push16 a (less than 4 bytes, so access format_address[1] would be wrong.

option b:
push32 d
push32 c
push32 b
push64 a (more than 4 bytes, so access format_address[1] would be wrong.

For performance reasons it would be fairly obvious that none of the examples
would apply, but I checked them anyway and that is not what happens: the format
pointer is put on the stack as 4 bytes.

So, to use your reasoning, is well established that if I have a buffer of 16
bytes, and if I declare a 1-entry (4-byte) int* PTR4 to point to the first byte
of that buffer, it is absolutely well defined that PTR4[0] will access bytes 0
to 3 of the buffer, PTR4[1] will access bytes 4 to 7, PTR4[2] will access bytes
8 to 11, and PTR4[3] will access bytes 12 to 15. It has been established for
several decades now that this is not undefined behaviour event if PTR4 is
declared as a 1-entry (4-byte) pointer, and this type of code runs predictably
on every platform in a very well-defined way. It is, in fact, the principle for
serialization, which I have done numerous times for the last 20 years.

I think it is clear why I think your arguments are missing the point, it is
simply not true that this behaviour is undefined.


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (9 preceding siblings ...)
  2010-08-11  1:57 ` rogerio at rilhas dot com
@ 2010-08-11  3:52 ` pinskia at gcc dot gnu dot org
  2010-08-11 11:21 ` rogerio at rilhas dot com
                   ` (46 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11  3:52 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #11 from pinskia at gcc dot gnu dot org  2010-08-11 03:52 -------
The ABI is not of concern here really.  The issue comes down to you have:
char *a;
char **b = &a;
use(b[1]);

It is undefined what happens when you access b[1].  It does not matter if the
ABI defines that the arguments are passed via the stack in ascending order or
not.  It could pass them via descending order.  Accessing an out of bounds
array is causing the issue here.

This is not about GCC vs MS Visual studio issue, this is a C/C++ standard issue
saying what you are doing is undefined.

>Another thing well defined in C is what happens when navigating an array out of
its bounds.

Kinda, you can go one past the array bounds for the address but you cannot
access it.  That is what the C/C++ standard says.  I can quote the standard if
needed.  Anything else is undefined.


-- 

pinskia at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (10 preceding siblings ...)
  2010-08-11  3:52 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 11:21 ` rogerio at rilhas dot com
  2010-08-11 11:21 ` rogerio at rilhas dot com
                   ` (45 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 11:21 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #13 from rogerio at rilhas dot com  2010-08-11 11:21 -------
Created an attachment (id=21453)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21453&action=view)
Source file (example 2)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (11 preceding siblings ...)
  2010-08-11 11:21 ` rogerio at rilhas dot com
@ 2010-08-11 11:21 ` rogerio at rilhas dot com
  2010-08-11 11:22 ` rogerio at rilhas dot com
                   ` (44 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 11:21 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #12 from rogerio at rilhas dot com  2010-08-11 11:20 -------
Created an attachment (id=21452)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21452&action=view)
Preprocessed file (with example 2)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (12 preceding siblings ...)
  2010-08-11 11:21 ` rogerio at rilhas dot com
@ 2010-08-11 11:22 ` rogerio at rilhas dot com
  2010-08-11 11:37 ` rguenth at gcc dot gnu dot org
                   ` (43 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 11:22 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #14 from rogerio at rilhas dot com  2010-08-11 11:22 -------
No, you are not correct. The equivalent code to what I'm doing would be
something like:

int buffer[4]; // 16 bytes on stack
buffer[0]=(int)&format
buffer[1]=(int)10
buffer[2]=(int)&another_string
buffer[3]=(int)20
call format_direct

format_direct:
char** PTR4=(char**)&buffer[0];
push PTR4
call format_indirect

format_indirect:
char** PTR4=get_from_stack  // gets PTR4 as pushed in format_direct
printf("%s %d %s %d",
PTR4[0],  // the same as (char*)buffer[0]
PTR4[1],  // the same as (int)buffer[1]
PTR4[2],  // the same as (char*)buffer[2]
PTR4[3]   // the same as (int)buffer[3]
);

This code must work, obviously. There is no undefined behaviour, it is correct
and portable code, and well defined and established. Even if the machine is 16
bits this would work without changes, just replace comment "16 bytes" by "8
bytes" and name PTR4 to PTR2, if you like the cosmetic changes.

I understand that when you look at your code you would call it undefined
behaviour, but your code is not the correct one: this one is. That is what I've
been trying to explain. The calling convention states that the parameters
should be packed ajdacent, like I did in the struct above, and not as you did
in your example, and getting the address of the parameter should get the
address of the start of the buffer, as I did manually.

Your code just ignored this and, of course, would not work (you don't even say
where you think the other parameters are). This is not an invention of mine, or
something that only works when I'm lucky, packing all parameters adjacent to
each other is something the compiler really needs to do, so if it gives me the
correct address of the first parameter then this code works *always* and is
very portable.

To show you that you are not correct I've done some changes to the source file,
where I created a new function "format_direct2" that does something like this:

void format_direct2(char* dst_buffer, int dst_buffer_size_bytes, const char*
format, ...) {
        int buffer[3];
        buffer[0]=(int)format;
        buffer[1]=(int)__DATE__;
        buffer[2]=(int)__TIME__;
        format_indirect(dst_buffer, dst_buffer_size_bytes, (const
char**)&buffer[0]);
}

The new code works always, of course, since I'm the one ensuring that the
parameters are adjacent, and I'm the one selecting the correct address to pass
to "format_indirect". I am, in fact, manually generating the 2 requirements -
compliance with the calling convention and passing the correct address to
"format_indirect". It also works with GCC, of course, even when optimized (as
expected) and I attach the corresponding files. So, when optimized, you get
"format_direct2" to work correctly and "format_direct" causes a segmentation
fault (and it shouldn't).

It would sure be interesting to see if you could quote some standard for C
which says that I'm not allowed to do this!!! I simply don't believe you can
find such text, or have I been wrong about C all my life and I can't use
pointers to navigate through buffers?? :-)


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (13 preceding siblings ...)
  2010-08-11 11:22 ` rogerio at rilhas dot com
@ 2010-08-11 11:37 ` rguenth at gcc dot gnu dot org
  2010-08-11 11:41 ` rguenth at gcc dot gnu dot org
                   ` (42 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 11:37 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #15 from rguenth at gcc dot gnu dot org  2010-08-11 11:37 -------
(In reply to comment #14)
> No, you are not correct. The equivalent code to what I'm doing would be
> something like:
> 
> int buffer[4]; // 16 bytes on stack
> buffer[0]=(int)&format
> buffer[1]=(int)10
> buffer[2]=(int)&another_string
> buffer[3]=(int)20
> call format_direct
> 
> format_direct:
> char** PTR4=(char**)&buffer[0];
> push PTR4
> call format_indirect
> 
> format_indirect:
> char** PTR4=get_from_stack  // gets PTR4 as pushed in format_direct
> printf("%s %d %s %d",
> PTR4[0],  // the same as (char*)buffer[0]
> PTR4[1],  // the same as (int)buffer[1]
> PTR4[2],  // the same as (char*)buffer[2]
> PTR4[3]   // the same as (int)buffer[3]
> );
> 
> This code must work, obviously. There is no undefined behaviour, it is correct
> and portable code, and well defined and established. Even if the machine is 16
> bits this would work without changes, just replace comment "16 bytes" by "8
> bytes" and name PTR4 to PTR2, if you like the cosmetic changes.
> 
> I understand that when you look at your code you would call it undefined
> behaviour, but your code is not the correct one: this one is. That is what I've
> been trying to explain. The calling convention states that the parameters
> should be packed ajdacent, like I did in the struct above, and not as you did
> in your example, and getting the address of the parameter should get the
> address of the start of the buffer, as I did manually.
> 
> Your code just ignored this and, of course, would not work (you don't even say
> where you think the other parameters are). This is not an invention of mine, or
> something that only works when I'm lucky, packing all parameters adjacent to
> each other is something the compiler really needs to do, so if it gives me the
> correct address of the first parameter then this code works *always* and is
> very portable.
> 
> To show you that you are not correct I've done some changes to the source file,
> where I created a new function "format_direct2" that does something like this:
> 
> void format_direct2(char* dst_buffer, int dst_buffer_size_bytes, const char*
> format, ...) {
>         int buffer[3];
>         buffer[0]=(int)format;
>         buffer[1]=(int)__DATE__;
>         buffer[2]=(int)__TIME__;
>         format_indirect(dst_buffer, dst_buffer_size_bytes, (const
> char**)&buffer[0]);
> }
> 
> The new code works always, of course, since I'm the one ensuring that the
> parameters are adjacent, and I'm the one selecting the correct address to pass
> to "format_indirect". I am, in fact, manually generating the 2 requirements -
> compliance with the calling convention and passing the correct address to
> "format_indirect". It also works with GCC, of course, even when optimized (as
> expected) and I attach the corresponding files. So, when optimized, you get
> "format_direct2" to work correctly and "format_direct" causes a segmentation
> fault (and it shouldn't).
> 
> It would sure be interesting to see if you could quote some standard for C
> which says that I'm not allowed to do this!!! I simply don't believe you can
> find such text, or have I been wrong about C all my life and I can't use
> pointers to navigate through buffers?? :-)

In the C language these implementation details are not exposed and thus
not accessible.  Hence your code invokes undefined behavior as you are
trying to circumvent this impossibility.


-- 

rguenth at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (14 preceding siblings ...)
  2010-08-11 11:37 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 11:41 ` rguenth at gcc dot gnu dot org
  2010-08-11 11:55 ` redi at gcc dot gnu dot org
                   ` (41 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 11:41 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #16 from rguenth at gcc dot gnu dot org  2010-08-11 11:41 -------
Btw, just use vsnprintf.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (15 preceding siblings ...)
  2010-08-11 11:41 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 11:55 ` redi at gcc dot gnu dot org
  2010-08-11 13:12 ` rogerio at rilhas dot com
                   ` (40 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: redi at gcc dot gnu dot org @ 2010-08-11 11:55 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #17 from redi at gcc dot gnu dot org  2010-08-11 11:55 -------
As already stated, what you are doing is not valid C or C++, the standards do
not guarantee the behaviour you are expecting w.r.t stack layout, and an
optimising C or C++ compiler follows the rules of the language standard. If you
want to rely on your assumptions write assembler or do not enable optimisation.



(In reply to comment #13)
> Created an attachment (id=21453)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21453&action=view) [edit]
> Source file (example 2)

> // linux (cannot use stdarg because this function does not take variable parameters and
> // so the compiler generates an error (shouldn't it be a warning?).

Have you checked how va_start is defined?


void va_start(va_list ap, parmN);
...
The parameter parmN is the identifier of the rightmost parameter in the
variable
parameter list in the function definition (the one just before the , ...).


You use *format_address as parmN, which is not an identifier.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (16 preceding siblings ...)
  2010-08-11 11:55 ` redi at gcc dot gnu dot org
@ 2010-08-11 13:12 ` rogerio at rilhas dot com
  2010-08-11 14:10 ` redi at gcc dot gnu dot org
                   ` (39 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 13:12 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #18 from rogerio at rilhas dot com  2010-08-11 13:11 -------
Of course vsnprintf was my first choice, as you can see from the WIN32 part of
the code I sent you. In WIN32 I can use vsnprint in a very natural and
predictable way in "format_indirect". In LINUX this cannot be used in
"format_indirect" as GCC does not allow me to use vsnprintf on a function that
doesn't take variable parameters. I tried to bypass it specifying variable
parameters for "format_indirect", but of course the results are wrong because
GCC will have placed the wrong address in "format_address" inside
"format_indirect". So, in fact, vsnprintf will have exactly the same problem as
I had, and I would report exactly the same bug like I did.

As you can see I've tried very hard to explain all details of the problem, and 
why this is a bug in GCC.

You just keep dismissing all my arguments without any justification whatsoever.
When you did justify I just proved your arguments to be false (no disrespect
intended) in the hope that this conversation would progress.

You don't explain why I can't rely on the calling convention to ensure the
parameters will be adjacent, and you don't explain why I can't use &format to
get the address of that packed data on the stack. You just keep invoking some
standard where these 2 things are alledgedly not defined but without
materializing it (which I don't believe you can anyway!). You have not yet
shown why GCC is not required to place the parameters correctly on the stack,
and why GCC does not need to give me the true &format.

So I'm stuck with your "you can't because you can't" replies and this
conversation will not progress any further, of course.

Best regards,
Rogerio


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (17 preceding siblings ...)
  2010-08-11 13:12 ` rogerio at rilhas dot com
@ 2010-08-11 14:10 ` redi at gcc dot gnu dot org
  2010-08-11 16:11 ` matz at gcc dot gnu dot org
                   ` (38 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: redi at gcc dot gnu dot org @ 2010-08-11 14:10 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #19 from redi at gcc dot gnu dot org  2010-08-11 14:10 -------
(In reply to comment #18)
> Of course vsnprintf was my first choice, as you can see from the WIN32 part of
> the code I sent you. In WIN32 I can use vsnprint in a very natural and
> predictable way in "format_indirect". In LINUX this cannot be used in

It's Linux (or GNU/Linux) not LINUX.

> "format_indirect" as GCC does not allow me to use vsnprintf on a function that
> doesn't take variable parameters. 

I explained why, see 7.15 in the C99 standard.


> I tried to bypass it specifying variable
> parameters for "format_indirect", but of course the results are wrong because
> GCC will have placed the wrong address in "format_address" inside
> "format_indirect". So, in fact, vsnprintf will have exactly the same problem as
> I had, and I would report exactly the same bug like I did.

Not if you use it correctly, which you are not doing.

void format_direct3(char* dst_buffer, int dst_buffer_size_bytes, const char*
format, ...) {
    va_list va;
    va_start(va, format);
    vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
    va_end(va);
}


> As you can see I've tried very hard to explain all details of the problem, and 
> why this is a bug in GCC.

GCC claims to support C and C++.  Can you point to part of either standard
which says your code is valid?

> You just keep dismissing all my arguments without any justification whatsoever.

What you're doing is not defined by the C or C++ standard.

GCC is a C and C++ compiler. Can you show where in the C or C++ standards it
says the stack must be laid out as you want?

> When you did justify I just proved your arguments to be false (no disrespect
> intended) in the hope that this conversation would progress.
> 
> You don't explain why I can't rely on the calling convention to ensure the
> parameters will be adjacent, 

Because the C and C++ standards do not make any guarantees about layout of
arguments in memory, so when using a C or C++ compiler to compile C or C++ code
you should not assume any particular layout.

> and you don't explain why I can't use &format to
> get the address of that packed data on the stack. You just keep invoking some
> standard where these 2 things are alledgedly not defined but without
> materializing it (which I don't believe you can anyway!). You have not yet
> shown why GCC is not required to place the parameters correctly on the stack,
> and why GCC does not need to give me the true &format.

The standard does not define how arguments are laid out, therefore it is
undefined.

> So I'm stuck with your "you can't because you can't" replies and this
> conversation will not progress any further, of course.

The onus is on you to show where in the C standard it says that your code is
well defined.  If the standard doesn't say it, it's not portable and not well
defined.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (18 preceding siblings ...)
  2010-08-11 14:10 ` redi at gcc dot gnu dot org
@ 2010-08-11 16:11 ` matz at gcc dot gnu dot org
  2010-08-11 17:04 ` rogerio at rilhas dot com
                   ` (37 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: matz at gcc dot gnu dot org @ 2010-08-11 16:11 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #20 from matz at gcc dot gnu dot org  2010-08-11 16:10 -------
A conforming variant of what you probably are trying to code is:
--------------------------------------------------------------------
#include <stdio.h>
#include <stdarg.h>

void format_indirect(char* dst_buffer, size_t dst_buffer_size_bytes,
                     const char *format, va_list va)
{
    vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
    dst_buffer[dst_buffer_size_bytes-1]=0;
}

void format_direct(char* dst_buffer, size_t dst_buffer_size_bytes,
                   const char* format, ...)
{
    va_list va;
    va_start (va, format);
    format_indirect(dst_buffer, dst_buffer_size_bytes, format, va);
    va_end (va);
}

int main(void)
{
    char buffer[1000];
    format_direct((char*)buffer, sizeof(buffer), "%s %s", __DATE__, __TIME__);
    printf("Result: \"%s\"\n", buffer);
    return 0;
}
-----------------------------------------------------------

Note how the va_list is constructed in the function that actually is
a varargs one, in particular how the necessary parameter is mentioned.
Note further how that va_list is passsed to the function that is not
varargs in order to capture all variable arguments of its caller.

There, no assumption on stack-layout.  It will work with all types and
ABIs, even those that happen to pass even some varargs in registers,
not on the stack.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (19 preceding siblings ...)
  2010-08-11 16:11 ` matz at gcc dot gnu dot org
@ 2010-08-11 17:04 ` rogerio at rilhas dot com
  2010-08-11 17:15 ` rogerio at rilhas dot com
                   ` (36 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 17:04 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #21 from rogerio at rilhas dot com  2010-08-11 17:04 -------
Subject: Re:  Indirect variable parameters sometimes cause
 segmentation fault

Yes, I was using that solution up to 2003, but then I stopped
using it in favour of the more confortable &format (the one I
showed you) because it is less error-prone and easier to automate
(no need for the va_list declaration, start, and end). My teams
usually have a lot of rookies (we have schollarship programs)
and bugs would popup a lot (like switching the order of
parameters, for example).

I could go back to using it, of course, but I already have a lot
of code done with this &format method, and it is not convenient
for me to go back and change anything in old code.

Anyway, I seem to have found a workaround for this problem
in GCC: it seems that if I use the &format before calling the
format_indirect then there will be no problem (still to conform).

void format_direct(char* dst_buffer, int dst_buffer_size_bytes, const 
char* format, ...) {
    const char** format_address=&format;
    format_indirect(dst_buffer, dst_buffer_size_bytes, format_address);
}

If I confirm this then this problem would no longer be blocking
and I would be able to live with it by creating a special macro
in Linux to use the &format before calling format_indirect:

#define GCC_SPECIFIC_ADDRESS_OF(format) const char** format_address(&format)

void format_direct(char* dst_buffer, int dst_buffer_size_bytes, const 
char* format, ...) {
    format_indirect(dst_buffer, dst_buffer_size_bytes, 
GCC_SPECIFIC_ADDRESS_OF(format));
}

... or something along these lines. Maybe I should also replace const
char** by some other GCC-specificy defined type (that would have
no effect on Windows) just to get compilation errors where people try
to pass &format directly whitout using the macro.

matz at gcc dot gnu dot org wrote:
> ------- Comment #20 from matz at gcc dot gnu dot org  2010-08-11 16:10 -------
> A conforming variant of what you probably are trying to code is:
> --------------------------------------------------------------------
> #include <stdio.h>
> #include <stdarg.h>
>
> void format_indirect(char* dst_buffer, size_t dst_buffer_size_bytes,
>                      const char *format, va_list va)
> {
>     vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
>     dst_buffer[dst_buffer_size_bytes-1]=0;
> }
>
> void format_direct(char* dst_buffer, size_t dst_buffer_size_bytes,
>                    const char* format, ...)
> {
>     va_list va;
>     va_start (va, format);
>     format_indirect(dst_buffer, dst_buffer_size_bytes, format, va);
>     va_end (va);
> }
>
> int main(void)
> {
>     char buffer[1000];
>     format_direct((char*)buffer, sizeof(buffer), "%s %s", __DATE__, __TIME__);
>     printf("Result: \"%s\"\n", buffer);
>     return 0;
> }
> -----------------------------------------------------------
>
> Note how the va_list is constructed in the function that actually is
> a varargs one, in particular how the necessary parameter is mentioned.
> Note further how that va_list is passsed to the function that is not
> varargs in order to capture all variable arguments of its caller.
>
> There, no assumption on stack-layout.  It will work with all types and
> ABIs, even those that happen to pass even some varargs in registers,
> not on the stack.
>
>
>   


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (20 preceding siblings ...)
  2010-08-11 17:04 ` rogerio at rilhas dot com
@ 2010-08-11 17:15 ` rogerio at rilhas dot com
  2010-08-11 17:49 ` pinskia at gcc dot gnu dot org
                   ` (35 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 17:15 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 10829 bytes --]



------- Comment #22 from rogerio at rilhas dot com  2010-08-11 17:15 -------
(In reply to comment #19)
> (In reply to comment #18)
> > Of course vsnprintf was my first choice, as you can see from the WIN32 part of
> > the code I sent you. In WIN32 I can use vsnprint in a very natural and
> > predictable way in "format_indirect". In LINUX this cannot be used in
> It's Linux (or GNU/Linux) not LINUX.

It is probably Win32, not WIN32. But thanks for the info.

> > "format_indirect" as GCC does not allow me to use vsnprintf on a function that
> > doesn't take variable parameters. 
> I explained why, see 7.15 in the C99 standard.


didn't need your explanations, I already knew it. That just shows you have been
missing the point from the start. I told why I didn't use vsnprintf, but you
seem to have missed it. Note that if I didn't need format_indirect to do the
actual work then I wouldn't have found any bug in GCC.

Maybe you are not realizing that format_indirect will not actually use
vanprintf, and will, instead, use my own parsing routines for several types of
parameters. The reason why I need a format_indirect is because I may have users
of my modules who are the ones that receive the variables parameters, and must
then pass the work on to my format_indirect to do the actual work.


> > I tried to bypass it specifying variable
> > parameters for "format_indirect", but of course the results are wrong because
> > GCC will have placed the wrong address in "format_address" inside
> > "format_indirect". So, in fact, vsnprintf will have exactly the same problem as
> > I had, and I would report exactly the same bug like I did.
> Not if you use it correctly, which you are not doing.
> void format_direct3(char* dst_buffer, int dst_buffer_size_bytes, const char*
> format, ...) {
>     va_list va;
>     va_start(va, format);
>     vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
>     va_end(va);
> }


You missed the point again. I don't have any problem with any of the
format_direct functions if they were to do the actual formatting work. But they
are not. Many of our older software uses specific parameter parsing, so we
developed functions over the years to parse format strings ourselves with
specific parsing instructions. To reuse code as much as possible the work is
done in a format_indirect function that can be called by any of the several
format_direct functions.

If I could use format_direct I would have no problem and the GCC bug would not
bug me at all. But that would mean copying and maintainig our special
functionality which currently resides in one format_indirect function in
several (maybe dozens) of diferent format_direct functions.

You must have noted that I used va_start/va_end in my WIN32 example, so you
must be aware that I know how to use it. You must also be aware that in the
*Linux* :-) version I used snprintf instead, so you must have realized that I
already knew that I could not use va_start/va_end in the format_indirect
function.

Microsoft's compiler developers didn't see the need to limit use of
va_start/va_end inside format_indirect, so I was able to use it without any
problem. I tried it in GCC anyway but to no avail. I understood it and moved
on, you were the one to bring vsnprintf as a solution to format_indirect which
I pointed out to you was not a solution (the GCC bug persists). However, now
you know that the actual work is not done by vsnprintf.



> > As you can see I've tried very hard to explain all details of the problem, and 
> > why this is a bug in GCC.
> GCC claims to support C and C++.  Can you point to part of either standard
> which says your code is valid?


Yes, sure. Or, at least, I can get close enough since I'm not interested in
really making you believe that GCC would be a better product if it didn't mess
up the pair of requirements I mentioned before. I'll just leave you to believe
whatever you like.

The first thing to note is that GCC doesn't only claim to be a C/C++ compiler:
it claims it can produce cdecl calls. So I will have to go a little outside of
the scope of C99.

The GCC manual "http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc.pdf" describes the
usage of cdecl as a possible option. Although not present in the code I sent
you I tried cdecl and stdcall specifiers and GCC didn't change anything in the
compiled code. This is the first suspicion that GCC is not conforming to what
it was supposed to do.

If GCC supports cdecl on a x86 plaform then it must support the packing of
parameters as defined for x86 (it is not standardize that I know of, but it is
well defined). I sugest reading
http://en.wikipedia.org/wiki/X86_calling_conventions for a number of references
on this parameter packing in the stack, one of my favorites is
"http://sco.com./developers/devspecs/abi386-4.pdf" where you can read in
"Figure 3-48: C Stack Frame" how the parameters should be placed on the stack.
GCC would only be cdecl-compliant if it were to conform to this specification
(I believe it does, I believe the problem lies with the &format operation).

The C99 states in "6.5.3.2 Address and indirection operators", in point 3, that
"The unary & operator yields the address of its operand". So, relating this to
the cdecl placement, &format should inequivocally return the address where
format is on the stack, and no other address. Why? Because the "format"
variable is nowhere else but on the stack. There is no other address to return,
so not returning the real stack address is a bug. Can you find anything in C99
that says that there is an exception to this? Something along the lines of "you
can return an arbitrary address if the user requests the address of a function
parameter"? Or cand you find any other way to define &format that would make
this statement ambiguous?

About the pointer arithmetic, you can find references in C99 such as that in
6.5.6-8 where it is well shown that there is no undefined behaviour when
accessing arrays out of bounds. The text clearly says "Moreover, if the
expression P points to the last element of an array object, the expression
(P)+1 points one past the last element of the array object. In other parts you
can read that E1[E2] is the same as *((E1)+(E2)). Also, you can read the
defition for adding integers to pointers to realize that I was correct about
format_address[1] pointing to the 4-byte element after the format.

So, as you can see, my reasoning is well backed-up by standards and well
defined interfaces. The parameters should be nicely packed on the stack as
cdecl, and &format should return the address of the format on the stack. And,
contrary to what you say, pointer arithmetic past the boundaries of an array is
well defined. Can you find any standards that refute these conclusions?


> > You just keep dismissing all my arguments without any justification whatsoever.
> What you're doing is not defined by the C or C++ standard.


What I'm doing is not defined, but each step of my operation is. Just like
a=b+c/3-40 is not defined in C/C++ standards, but each of its individual
operations is.



> GCC is a C and C++ compiler. Can you show where in the C or C++ standards it
> says the stack must be laid out as you want?


Above you can see that my first operation is backed by a well defined cdecl
convention (although not standardized). Did GCC invent a new meaning for cdecl
based on the fact that is not standardized or does it conform to the well
defined meaning of cdecl as shown in the document I mentioned?

The other operation, &format, is also well defined and I showed you in C99
where to find it. I didn't read all the standard though, so I'm open to the
possibility that you show me where I can see in the standard that
&function_param is not applicable or defined. Note that I can pass literals to
functions, and inside I can always get the address of those literals placed on
the stack.

Pointer arithmetic to access out of bounds elements of arrays is also well
defined in C99, or can you find anywhere in C99 that P+1 will not point to the
next element if it is pointing to a location on the stack?


> > When you did justify I just proved your arguments to be false (no disrespect
> > intended) in the hope that this conversation would progress.
> > 
> > You don't explain why I can't rely on the calling convention to ensure the
> > parameters will be adjacent, 
> Because the C and C++ standards do not make any guarantees about layout of
> arguments in memory, so when using a C or C++ compiler to compile C or C++ code
> you should not assume any particular layout.


Yes, you are right. That's why you would need to "step out of the C/C++" box
and realize that GCC also claims to be cdecl compliant. If you do that you will
realize that that implies a certain way to place parameters in memory. So I
would be able to reply on it, if it were done properly, as is the case with MS
compilers.


> > and you don't explain why I can't use &format to
> > get the address of that packed data on the stack. You just keep invoking some
> > standard where these 2 things are alledgedly not defined but without
> > materializing it (which I don't believe you can anyway!). You have not yet
> > shown why GCC is not required to place the parameters correctly on the stack,
> > and why GCC does not need to give me the true &format.
> The standard does not define how arguments are laid out, therefore it is
> undefined.


It is not undefined, I just showed you that. If you stick to C/C++ as the proof
that GCC has no bug then GCC should remove the claim that it is cdecl compliant
from its manuals.

If GCC is already cdecl compliant (as viewing disassembly code sugests) then
GCC has a bug in the &format statement, and that is clearly defined in the C99
standard.


> > So I'm stuck with your "you can't because you can't" replies and this
> > conversation will not progress any further, of course.
> The onus is on you to show where in the C standard it says that your code is
> well defined.  If the standard doesn't say it, it's not portable and not well
> defined.

I don't think the onus should be on my side. It shouldn't be so hard for me to
show you that GCC has a bug. I consider this to be way too obvious to justify
such reluctance from you to accept it.

You continuously laim it is not defined, yet I easilly showed that all my
claims are backed up by standards and well defined concepts.

You are the one who don«t seem to be making any effort to even understand the
importance of my report (as sugested by the quick way you sugested that I used
vsnprintf which is, by your own words, not applicable in format_indirect).

Anyway, that enough for me, I already spent way too much energy and time trying
to show you what I think should be obvious.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (21 preceding siblings ...)
  2010-08-11 17:15 ` rogerio at rilhas dot com
@ 2010-08-11 17:49 ` pinskia at gcc dot gnu dot org
  2010-08-11 17:57 ` redi at gcc dot gnu dot org
                   ` (34 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11 17:49 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #23 from pinskia at gcc dot gnu dot org  2010-08-11 17:49 -------
First off I already mentioned what is undefined in this example in comment #11.
 The part of the standard that mentions about arrays.  And how the address of a
scalar is considered an array of size 1.  I don't have the standard in front of
me right now but those are what I remember from the standard.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (22 preceding siblings ...)
  2010-08-11 17:49 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 17:57 ` redi at gcc dot gnu dot org
  2010-08-11 19:51 ` rogerio at rilhas dot com
                   ` (33 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: redi at gcc dot gnu dot org @ 2010-08-11 17:57 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #24 from redi at gcc dot gnu dot org  2010-08-11 17:57 -------
(In reply to comment #22)
> 
> If GCC supports cdecl on a x86 plaform then it must support the packing of
> parameters as defined for x86 (it is not standardize that I know of, but it is
> well defined). I sugest reading
> http://en.wikipedia.org/wiki/X86_calling_conventions for a number of references
> on this parameter packing in the stack, one of my favorites is
> "http://sco.com./developers/devspecs/abi386-4.pdf" where you can read in
> "Figure 3-48: C Stack Frame" how the parameters should be placed on the stack.

That's a good reference. Did you see page 70?

If you're not interested in writing portable code, don't blame the compiler.


> Anyway, that enough for me, I already spent way too much energy and time 

At least we can agree on that.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (23 preceding siblings ...)
  2010-08-11 17:57 ` redi at gcc dot gnu dot org
@ 2010-08-11 19:51 ` rogerio at rilhas dot com
  2010-08-11 19:54 ` pinskia at gcc dot gnu dot org
                   ` (32 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 19:51 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #25 from rogerio at rilhas dot com  2010-08-11 19:51 -------
(In reply to comment #24)
> (In reply to comment #22)
> > 
> > If GCC supports cdecl on a x86 plaform then it must support the packing of
> > parameters as defined for x86 (it is not standardize that I know of, but it is
> > well defined). I sugest reading
> > http://en.wikipedia.org/wiki/X86_calling_conventions for a number of references
> > on this parameter packing in the stack, one of my favorites is
> > "http://sco.com./developers/devspecs/abi386-4.pdf" where you can read in
> > "Figure 3-48: C Stack Frame" how the parameters should be placed on the stack.
> That's a good reference. Did you see page 70?
> If you're not interested in writing portable code, don't blame the compiler.
> > Anyway, that enough for me, I already spent way too much energy and time 
> At least we can agree on that.

The reason for the reference of page 70 is exactly because of compilers like
GCC which claim to be cdecl compliant and are not. If GCC would do what it
claims to do and be cdecl compliant I would not blame the compiler and my code
(and code from many others) would be portable.

In other words my code is not portable because GCC is not doing what it should.
GCC causes code not to be portable a lot of times, like in the following case
(which does not compile because of GCC's shortcommings):

class Temp {
public:
Temp(int b);
Temp(Temp& t);
void operator=(Temp& t);
};

void func(int a, class Temp& b, int c);

func(10, Temp(20), 30); // error

This code does not compile in GCC, and so is not portable. That's shortcomming
of GCC that makes my code be not portable, not me. Its GCC's fault that code
that invokes Temp(20) as a parameter is not portable, not the programmer's
fault.

Unfortunately, conversations like this one show that GCC will never be perfect,
because people like you will insist that the compiler doesn't need to do what I
said it should (even when facing the obvious references that I've posted), and
prove that page 70 is right about warning programmers not to rely on compilers
to do correct parameter placements.

My personal experience is that GCC is the cause for such portability problems.
You still insist that GCC doesn't need to improve in this respect, and that
shows why GCC will never be as good as other compilers. Microsoft, for example,
appreciates comments like mine because it helps them improve the product, but
you just want to dismiss it as bad code on my part. I know Microsoft's people
get paid to do so, but, still, I'm talking about the right mind set.

Note that you have not stated why you think my reply #22 is wrong, and I'm
pretty sure that's because you can't. All my arguments are solidly backed up,
but you just looked at page 70, interpreted it incorrectly (because you didn't
realize that compilers like GCC are the ones responsible for that remark), and
didn't bother to see that I'm right about my arguments. You just say that I
can't do it, but I have shown why I should be able to do it. You just dismissed
it, I think is a loss for GCC, but whatever.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (24 preceding siblings ...)
  2010-08-11 19:51 ` rogerio at rilhas dot com
@ 2010-08-11 19:54 ` pinskia at gcc dot gnu dot org
  2010-08-11 20:04 ` rogerio at rilhas dot com
                   ` (31 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11 19:54 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #26 from pinskia at gcc dot gnu dot org  2010-08-11 19:54 -------
>This code does not compile in GCC, and so is not portable.

No it is not portable because that code is just plain invalid; though MS
accepts it as it is implementing something called "move constructor" as an
extension.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (25 preceding siblings ...)
  2010-08-11 19:54 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 20:04 ` rogerio at rilhas dot com
  2010-08-11 20:07 ` rogerio at rilhas dot com
                   ` (30 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 20:04 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #27 from rogerio at rilhas dot com  2010-08-11 20:04 -------
(In reply to comment #26)
> >This code does not compile in GCC, and so is not portable.
> No it is not portable because that code is just plain invalid; though MS
> accepts it as it is implementing something called "move constructor" as an
> extension.

I already told you "you can't because you can't" (or in this case "is plain
invalid") is not an answer. Please explain concisely:

a) If GCC is cdecl compliant should it put the parameters on the stack as the
figure 3-48 shows? Can you quote any standard that there is any exception that
GCC can take advantage of and still claim to be cdecl-compliant?

b) When I code &format shouldn't GCC give me the address of the format
parameter on the stack? Can you quote any standard that shows that the quote I
shoewd you of C99 has an exception anywhere that is applicable to this case?

Both in a) and b) the answer should be yes. A good non-buggy compiler will do
both things a)+b), as Microsoft does (without any extension).

If GCC can be made to do a)+b) simultaneously then don't worry about the
portability of my code because I just need a)+b) together and I will have no
problem, just leave the rest to me and don't you worry.

I think it would settle the issue if you could just simply answer these 2
questions a) and b) directly and clearly.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (26 preceding siblings ...)
  2010-08-11 20:04 ` rogerio at rilhas dot com
@ 2010-08-11 20:07 ` rogerio at rilhas dot com
  2010-08-11 20:33 ` rguenth at gcc dot gnu dot org
                   ` (29 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 20:07 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #28 from rogerio at rilhas dot com  2010-08-11 20:07 -------
(In reply to comment #23)
> First off I already mentioned what is undefined in this example in comment #11.
>  The part of the standard that mentions about arrays.  And how the address of a
> scalar is considered an array of size 1.  I don't have the standard in front of
> me right now but those are what I remember from the standard.


Right. And I clearly explained in my comment #14 why you were wrong. Getting
back to comment #11 so that we can run around in circles brings no improvement
to this conversation, and you will just keep on being wrong, even if you had
the standard in front of you, because your example in comment #11 does not
correspond to the code I'm doing. My comment #14 explains what is the correct
code for comparison.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (27 preceding siblings ...)
  2010-08-11 20:07 ` rogerio at rilhas dot com
@ 2010-08-11 20:33 ` rguenth at gcc dot gnu dot org
  2010-08-11 20:58 ` rogerio at rilhas dot com
                   ` (28 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 20:33 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #29 from rguenth at gcc dot gnu dot org  2010-08-11 20:33 -------
(In reply to comment #28)
> (In reply to comment #23)
> > First off I already mentioned what is undefined in this example in comment #11.
> >  The part of the standard that mentions about arrays.  And how the address of a
> > scalar is considered an array of size 1.  I don't have the standard in front of
> > me right now but those are what I remember from the standard.
> 
> 
> Right. And I clearly explained in my comment #14 why you were wrong. Getting
> back to comment #11 so that we can run around in circles brings no improvement
> to this conversation, and you will just keep on being wrong, even if you had
> the standard in front of you, because your example in comment #11 does not
> correspond to the code I'm doing. My comment #14 explains what is the correct
> code for comparison.

We're indeed running in circles.  Maybe you can find someone that can explain
to you better on comp.lang.c.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (28 preceding siblings ...)
  2010-08-11 20:33 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 20:58 ` rogerio at rilhas dot com
  2010-08-11 21:02 ` pinskia at gcc dot gnu dot org
                   ` (27 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 20:58 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3291 bytes --]



------- Comment #30 from rogerio at rilhas dot com  2010-08-11 20:58 -------
Really? Your comment #11 has so many mistakes in it that maybe you are the one
who should learn a little bit more on C.

>The ABI is not of concern here really.  The issue comes down to you have:
>char *a;
>char **b = &a;
>use(b[1]);

This comment just means you missed the point. Maybe you just memorized the C
standar, maybe not, but you didn't understand that I was doing something
different. Did you miss the part in my comment #14 where I mentioned that &a
does not point to only 4 bytes but, instead, 16 bytes? Didn«t you understand
the equivalent code would be:

char* a[4];
char **b =&a[0];
use(b[1]);

Didn't you realize that there is nothing wrong with this code? Its basic C. The
code does not work because GCC is not doing its job right, otherwise, by cdecl
definition, there would a would be an array of 4 pointers, like I showed. It
seems you didn't understand, but it is, in fact, quite simple. Check what cdecl
means, then you will realize that the 4 parameters are supposed to be
equivalent to char* a[4]. Nothing else I can do here, really, if you don«t
understand this then maybe you should be responsible for answering to comments
on such an important project as GCC.

>It is undefined what happens when you access b[1].  It does not matter if the
>ABI defines that the arguments are passed via the stack in ascending order or
>not.  It could pass them via descending order.  Accessing an out of bounds
>array is causing the issue here.

This is very wrong again. Don«t hide in out of bounds array. The point is
exactly that, you are wrong about what the problem is. The problem is that the
address GCC gives me is not to the 4 packed parameters, not the out of bounds.
If GCC packed the 4 entries there would be no out of bounds problem. Maybe you
need to learn C, I did learn it and well, so I know what a pointer does and
what happens when you go out of bounds. So the problem is the underlying buffer
of data created by GCC is bad, not that I use the 1-entry pointer to an array
to access the following elements. You are just wrong, and I seem to be unable
to make you see just how wrong you are.

>This is not about GCC vs MS Visual studio issue, this is a C/C++ standard issue
>saying what you are doing is undefined.

Can you quote some part of the standard to back up your claims? I did backup my
claims, you have not yet backed up yours.

>Another thing well defined in C is what happens when navigating an array out of
its bounds.

Kinda, you can go one past the array bounds for the address but you cannot
access it.  That is what the C/C++ standard says.  I can quote the standard if
needed.  Anything else is undefined.

You are just wrong again.

char* a[4];
char** b=&a[0];
access(b[0], b[1], b[2], b[3]).

This code is valid although b is a pointer to one and only one address. This is
the example in my code (assuming cdecl), you can try to avoid it, and compare
to wrong code like you did in comment #11, but that will not be helpful to the
GCC project, you will just keep wasting resources.

So, as you can see, there is nothing correct about your comment #11. Should't
you be reading something somewhere then?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (29 preceding siblings ...)
  2010-08-11 20:58 ` rogerio at rilhas dot com
@ 2010-08-11 21:02 ` pinskia at gcc dot gnu dot org
  2010-08-11 21:12 ` rogerio at rilhas dot com
                   ` (26 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11 21:02 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #31 from pinskia at gcc dot gnu dot org  2010-08-11 21:02 -------
>Didn't you understand the equivalent code would be:

No, as the variables act the same if they are automatic variables or arguments.
 there is no different between the two.  That has been my point from the
beginning.

I think it is time for me to end my part and say please follow up to the C
standards news group as we are going in circles as a misunderstanding about ABI
and how arguments are passed have no concern to what the C standard says about
variables (automatic and arguments) and the size of an array for an address of
one.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (30 preceding siblings ...)
  2010-08-11 21:02 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 21:12 ` rogerio at rilhas dot com
  2010-08-11 21:16 ` pinskia at gcc dot gnu dot org
                   ` (25 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 21:12 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #32 from rogerio at rilhas dot com  2010-08-11 21:12 -------
(In reply to comment #31)
> >Didn't you understand the equivalent code would be:
> No, as the variables act the same if they are automatic variables or arguments.
>  there is no different between the two.  That has been my point from the
> beginning.

Wrong again. The cdecl definition is for parameters, there is no such thing for
automatic variables. So I can expect a given packing of arguments in a
cdecl-compliant compiler, and I can expect no such thing from automatic
variables.

Can you backup your claim? (I'm not really interested, just to let you know
that you missed a critical aspect again)


> I think it is time for me to end my part and say please follow up to the C
> standards news group as we are going in circles as a misunderstanding about ABI
> and how arguments are passed have no concern to what the C standard says about
> variables (automatic and arguments) and the size of an array for an address of
> one.

Yes, I agree that is better as you don't backup anything you say. You didn't
even bother to answer to a) and b) of my comment 27 (and you woldn't,
obviously, as you dismiss cdecl as an important part to this discussion). I can
only assume that that is because you simply can't, since you so cleverly
avoided answering the questions I placed there which would surely settle the
matter.

Anyway, I found a workaround that makes GCC behave properly so I got my code
running again. So you can leave the bug as is and it won't bother me anymore.


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|blocker                     |normal


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (31 preceding siblings ...)
  2010-08-11 21:12 ` rogerio at rilhas dot com
@ 2010-08-11 21:16 ` pinskia at gcc dot gnu dot org
  2010-08-11 21:27 ` redi at gcc dot gnu dot org
                   ` (24 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11 21:16 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #33 from pinskia at gcc dot gnu dot org  2010-08-11 21:16 -------
Yes GCC implements that ABI and &argument will get you the address of that
argument.  But that does not deter from that &argument will produce an array of
size 1 rather than what you want which is the rest of the arguments too.

Does that answer your question about how I could just ignore the ABI in the
context of the C/C++ standard?  The ABI only says how they are passed and not
how you can access them through C/C++ code.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (32 preceding siblings ...)
  2010-08-11 21:16 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 21:27 ` redi at gcc dot gnu dot org
  2010-08-11 22:17 ` rogerio at rilhas dot com
                   ` (23 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: redi at gcc dot gnu dot org @ 2010-08-11 21:27 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #34 from redi at gcc dot gnu dot org  2010-08-11 21:27 -------
(In reply to comment #25)
> In other words my code is not portable because GCC is not doing what it should.
> GCC causes code not to be portable a lot of times, like in the following case
> (which does not compile because of GCC's shortcommings):
> 
> class Temp {
> public:
> Temp(int b);
> Temp(Temp& t);
> void operator=(Temp& t);
> };
> 
> void func(int a, class Temp& b, int c);
> 
> func(10, Temp(20), 30); // error

ISO/IEC 14882:2003(E) 8.5.3 [dcl.init.ref] paragraph 5

> This code does not compile in GCC, and so is not portable. That's shortcomming
> of GCC that makes my code be not portable, not me. Its GCC's fault that code
> that invokes Temp(20) as a parameter is not portable, not the programmer's
> fault.

ibid.

> Unfortunately, conversations like this one show that GCC will never be perfect,
> because people like you will insist that the compiler doesn't need to do what I
> said it should (even when facing the obvious references that I've posted), and
> prove that page 70 is right about warning programmers not to rely on compilers
> to do correct parameter placements.

What a charming idea, that a compiler could become perfect by doing "what I
said it should"

> My personal experience is that GCC is the cause for such portability problems.
> You still insist that GCC doesn't need to improve in this respect, and that
> shows why GCC will never be as good as other compilers. Microsoft, for example,
> appreciates comments like mine because it helps them improve the product, but
> you just want to dismiss it as bad code on my part. I know Microsoft's people
> get paid to do so, but, still, I'm talking about the right mind set.

Oh, how delightfully quaint!


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (33 preceding siblings ...)
  2010-08-11 21:27 ` redi at gcc dot gnu dot org
@ 2010-08-11 22:17 ` rogerio at rilhas dot com
  2010-08-11 22:27 ` rguenth at gcc dot gnu dot org
                   ` (22 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:17 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #35 from rogerio at rilhas dot com  2010-08-11 22:16 -------
(In reply to comment #33)
> Yes GCC implements that ABI and &argument will get you the address of that
> argument.

If that is so then the format parameter will be placed at some address X, param
1 at address X+4, param 2 at address X+8, and param 3 at X+12. Figure 3-48
shows these addresses to be very predictable and well defined. It is very
important for you to follow this reasoning, as this makes all the difference.
This is what makes X an array of 4 entries, and not simply an array of 1
isolated entry.


> But that does not deter from that &argument will produce an array of
> size 1 rather than what you want which is the rest of the arguments too.

Can you backup your claim that "&argument will produce an array of size 1"? Can
you even backup the claim that &argument "produces" any array at all? As I
showed using C99, the & just produces a value X (an address which can be
travelled without boundary issues), so C99 shows that "&argument" does not
"produce" an array, nor allocates storage for a 1-entry copy of "argument" at
some unpredictable address Y (C99 clearly states that &a retuns "address of a",
not "address of copy of a"). So I don't see how you could ever backup your
claim with any standard, but I'm open to be surprised by your creativity! :-)

Based on C99 const char** PTR4=&format will set PTR4 to X. It's all good as
long as PTR4 contains the value X. As C99 defines this, GCC doesn't have the
option to copy the "format" to some random address Y and return it when I ask
for "&format". It simply should not do this. I've backed this claim with C99
text that states that & operator is the address of the item, not the address of
a copy of the item invented by the compiler.

I also showed you in C99 that PTR4[0] accesses the 4 bytes of address X, and
I've backed up my claim (based on C99) that PTR4[1] will access the 4 bytes at
X+4 (i.e the 4 bytes of param 1), and that there is no "size of array
limitation" specified in C99. Similarly, PTR4[2] will access the 4 bytes at
X+8, (i.e the 4 bytes of param 2), and so on. I've clearly backed up this with
C99.

So, all this is backed up. Can you refute the reasoning up to this point with
any C99 reference? Or a reference to any other standard for that matter?

> Does that answer your question about how I could just ignore the ABI in the
> context of the C/C++ standard?  The ABI only says how they are passed and not
> how you can access them through C/C++ code.

So no, not really. If the ABI is respected then the 4 parameters will be stored
at predictable places, all together, as a 4-entry array at address X, which is
fundamental for me to access them using a PTR4 set to X.

If you told me right from the start that GCC didn't comply to cdecl, or that it
did but only sometimes, then this conversation would have ended immediately,
because I would have absolutely no way to trust that the 4 items would be
present at contiguous bytes X to X+15, and I would, therefore, not be able to
access PTR4[1], PTR4[2], and so on. This should help you understand why the ABI
is an important part of this problem, and where I base my claim that GCC's
behaviour is wrong.

So, if GCC were not cdecl-compliant, I would have no other option but to shut
up and think about new approaches in my code. Well, maybe I would not just shut
up and maybe I would then complain that GCC should be cdecl-compliant always,
but I would not call it a bug and I would post it as a feature request.

You could reason that the ABI was not important if the compiler were free to
create a copy of "format" to some address Y when I ask for "&format" (as in
that case it would probably just copy "format" and not the remaining 3
parameters to location Y - hence you would be right, an array of size 1), but
C99 says the compiler cannot do that because &format is X (the address of the
item, not Y the address of a copy of it).

But GCC does not return X when I ask for "&format", at least not always (as
sometimes returns a random Y), and it should (as I backed up with C99).

If under GCC "&argument will produce an array of size 1 [with a copy of format
and not of the other parameters]" then you would be right and you would be
proving GCC to have a bug that contradicts C99.

If GCC didn't have a bug it would comply with C99 and would return X, which the
cdecl ABI states is a 4-entry array, not 1-entry array as you claimed (making
your claim wrong).

So you are right because GCC has a bug, if it hadn't you would be wrong. In
other words, what you say in fact happens in real life because GCC is not
strictly conforming to C99 (and while that happens you are right to say that is
the current behaviour to "&argument will produce an array of size 1"), but if
GCC behaved as C99 says it should then what you say would not be hapening in
real life (and so you would be wrong when saying "&argument will produce an
array of size 1").

I have the feeling I was able to explain myself better this time. Was I?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (34 preceding siblings ...)
  2010-08-11 22:17 ` rogerio at rilhas dot com
@ 2010-08-11 22:27 ` rguenth at gcc dot gnu dot org
  2010-08-11 22:31 ` rguenth at gcc dot gnu dot org
                   ` (21 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 22:27 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #36 from rguenth at gcc dot gnu dot org  2010-08-11 22:27 -------
(In reply to comment #35)
> (In reply to comment #33)
> > Yes GCC implements that ABI and &argument will get you the address of that
> > argument.
> 
> If that is so then the format parameter will be placed at some address X, param
> 1 at address X+4, param 2 at address X+8, and param 3 at X+12. Figure 3-48
> shows these addresses to be very predictable and well defined. It is very
> important for you to follow this reasoning, as this makes all the difference.
> This is what makes X an array of 4 entries, and not simply an array of 1
> isolated entry.

It doesn't make it an array in the C sense.

> > But that does not deter from that &argument will produce an array of
> > size 1 rather than what you want which is the rest of the arguments too.
> 
> Can you backup your claim that "&argument will produce an array of size 1"? Can
> you even backup the claim that &argument "produces" any array at all? As I
> showed using C99, the & just produces a value X (an address which can be
> travelled without boundary issues), so C99 shows that "&argument" does not
> "produce" an array, nor allocates storage for a 1-entry copy of "argument" at
> some unpredictable address Y (C99 clearly states that &a retuns "address of a",
> not "address of copy of a"). So I don't see how you could ever backup your
> claim with any standard, but I'm open to be surprised by your creativity! :-)
> 
> Based on C99 const char** PTR4=&format will set PTR4 to X. It's all good as
> long as PTR4 contains the value X. As C99 defines this, GCC doesn't have the
> option to copy the "format" to some random address Y and return it when I ask
> for "&format". It simply should not do this. I've backed this claim with C99
> text that states that & operator is the address of the item, not the address of
> a copy of the item invented by the compiler.
> 
> I also showed you in C99 that PTR4[0] accesses the 4 bytes of address X, and
> I've backed up my claim (based on C99) that PTR4[1] will access the 4 bytes at
> X+4 (i.e the 4 bytes of param 1), and that there is no "size of array
> limitation" specified in C99. Similarly, PTR4[2] will access the 4 bytes at
> X+8, (i.e the 4 bytes of param 2), and so on. I've clearly backed up this with
> C99.
> 
> So, all this is backed up. Can you refute the reasoning up to this point with
> any C99 reference? Or a reference to any other standard for that matter?

&X gives you an address of X which happens to be on the stack.  Following
parameters happen to be in adjacent stack slots.  Still C does not give
you a way to access adjacent parameters by doing pointer arithmetic on
&X.  &X does _not_ get you access to anything like a "stack" as there is
no such concept in the C language.  In

foo (int x, int y, int z)

there are only x, y and z.  There is no array of parameters, the only
"arrays" are that of implicit size 1 at locations &x, &y and &z which
allows you to compute &x + 1 (but not dereference that pointer).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (35 preceding siblings ...)
  2010-08-11 22:27 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 22:31 ` rguenth at gcc dot gnu dot org
  2010-08-11 22:35 ` rogerio at rilhas dot com
                   ` (20 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 22:31 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #37 from rguenth at gcc dot gnu dot org  2010-08-11 22:30 -------
Btw, 6.5.6/7 "For the purposes of these operators, a pointer to an object that
is
not an element of an array behaves the same as a pointer to the first element
of an array of length one with the type of the object as its element type."


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (36 preceding siblings ...)
  2010-08-11 22:31 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 22:35 ` rogerio at rilhas dot com
  2010-08-11 22:37 ` rogerio at rilhas dot com
                   ` (19 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:35 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #38 from rogerio at rilhas dot com  2010-08-11 22:35 -------
(In reply to comment #34)
> (In reply to comment #25)
> > In other words my code is not portable because GCC is not doing what it should.
> > GCC causes code not to be portable a lot of times, like in the following case
> > (which does not compile because of GCC's shortcommings):
> > 
> > class Temp {
> > public:
> > Temp(int b);
> > Temp(Temp& t);
> > void operator=(Temp& t);
> > };
> > 
> > void func(int a, class Temp& b, int c);
> > 
> > func(10, Temp(20), 30); // error
> ISO/IEC 14882:2003(E) 8.5.3 [dcl.init.ref] paragraph 5

Thanks for this. I didn't know why GCC was unable to compile such code and now
I know: GCC is unable to convert a initialization passed as parameter to an
lvalue. Microsoft's compiler does know how to do that - there is no problem in
getting the address of such temporary variables, right? Oh, wrong, GCC can't,
that's just too hard on the poor thing.

... oh well, let's just not call that a portability issue created by GCC,
because no one explained to its developers how to get the address of a
temporary variable. Let's just not initialize temporary variables and stick to
the lowest common denominator, which is GCC.

Really?? Was that rally the explanation you wanted to provide??? I think its
just embarassing. Note that I didn't open a bug for this issue because I can,
in fact, reduce to the lowest common denominator. So, I can live without
(although not as confortably).

> > This code does not compile in GCC, and so is not portable. That's shortcomming
> > of GCC that makes my code be not portable, not me. Its GCC's fault that code
> > that invokes Temp(20) as a parameter is not portable, not the programmer's
> > fault.
> ibid.
> > Unfortunately, conversations like this one show that GCC will never be perfect,
> > because people like you will insist that the compiler doesn't need to do what I
> > said it should (even when facing the obvious references that I've posted), and
> > prove that page 70 is right about warning programmers not to rely on compilers
> > to do correct parameter placements.
> What a charming idea, that a compiler could become perfect by doing "what I
> said it should"

You must have missed something in the discussion because you failed to see that
"what I say" is what "C99+cdecl" say. Please forgive me for cutting sentences
short, I didn't think anyone would start making comments without reading the
whole conversation, my bad.

... is it still a charming idea after you read all the backups to my claims?


> > My personal experience is that GCC is the cause for such portability problems.
> > You still insist that GCC doesn't need to improve in this respect, and that
> > shows why GCC will never be as good as other compilers. Microsoft, for example,
> > appreciates comments like mine because it helps them improve the product, but
> > you just want to dismiss it as bad code on my part. I know Microsoft's people
> > get paid to do so, but, still, I'm talking about the right mind set.
> Oh, how delightfully quaint!


It is, isn't it? And it makes sense too, doesn't it? I bet that thinking that
GCC needs not improve on the stuff I commented here is a sure way to get you
there fast. I'm sorry I even tried!


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (37 preceding siblings ...)
  2010-08-11 22:35 ` rogerio at rilhas dot com
@ 2010-08-11 22:37 ` rogerio at rilhas dot com
  2010-08-11 22:48 ` rguenth at gcc dot gnu dot org
                   ` (18 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:37 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #39 from rogerio at rilhas dot com  2010-08-11 22:37 -------
(In reply to comment #37)
> Btw, 6.5.6/7 "For the purposes of these operators, a pointer to an object that
> is
> not an element of an array behaves the same as a pointer to the first element
> of an array of length one with the type of the object as its element type."

No problem, as long as it doesn't make a copy. I clearly stated this, and
explained with C99, that even 1-entry arrays can be navigated beyond the
boundaries. I thoroughly explained the arithmetic. Where did you read that
1-entry arrays can be copied to a different location when someone requests the
address operator?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (38 preceding siblings ...)
  2010-08-11 22:37 ` rogerio at rilhas dot com
@ 2010-08-11 22:48 ` rguenth at gcc dot gnu dot org
  2010-08-11 22:50 ` rogerio at rilhas dot com
                   ` (17 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rguenth at gcc dot gnu dot org @ 2010-08-11 22:48 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #40 from rguenth at gcc dot gnu dot org  2010-08-11 22:48 -------
(In reply to comment #39)
> (In reply to comment #37)
> > Btw, 6.5.6/7 "For the purposes of these operators, a pointer to an object that
> > is
> > not an element of an array behaves the same as a pointer to the first element
> > of an array of length one with the type of the object as its element type."
> 
> No problem, as long as it doesn't make a copy.

Why do you think GCC makes it the address of a copy?

> I clearly stated this, and
> explained with C99, that even 1-entry arrays can be navigated beyond the
> boundaries. I thoroughly explained the arithmetic. Where did you read that
> 1-entry arrays can be copied to a different location when someone requests the
> address operator?

You are wrong here.  The next paragraph, 6.5.6/8, explains that,
"... otherwise the behavior is undefined.  If the result points one past
the last element of the array object, it shall not be used as the operator
of a unary * operator that is evaluated.".  Where I point you to
6.5.3.2/3 if you now claim that x[2] isn't invoking the unary * operator.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (39 preceding siblings ...)
  2010-08-11 22:48 ` rguenth at gcc dot gnu dot org
@ 2010-08-11 22:50 ` rogerio at rilhas dot com
  2010-08-11 22:51 ` rogerio at rilhas dot com
                   ` (16 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:50 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2178 bytes --]



------- Comment #41 from rogerio at rilhas dot com  2010-08-11 22:50 -------
> It doesn't make it an array in the C sense.

What is an array in the C sense? Isn't it a sequence of entries? Is there any
other concept to go along with it that allows PTR4 to be set to any other value
than X? If so, where did you read it? I read in C99 that a pointer is simply a
variable that contains an address, and that C doesn't navigate "arrays in the C
sense" in anyway diferently than with "simple pointers". Do you have a C99
section that shows a distinction significant to this issue?

> &X gives you an address of X which happens to be on the stack.  Following
> parameters happen to be in adjacent stack slots.  Still C does not give
> you a way to access adjacent parameters by doing pointer arithmetic on
> &X.

Can you explain then how &X gets the format parameter from the stack and X[1]
doesn't get the next adjacent entry on the stack? Note that C99 is pretty clear
about the fact that X[1] will access bytes 4 to 7 after X. Can you backup your
claim with C99 or any other reference besides your personal interpretation?

> &X does _not_ get you access to anything like a "stack" as there is
> no such concept in the C language.

No problem. I don«t want PTR4 to be a specific "pointer to stack", I want it to
be a "general pointer to memory". I don«t need more than that and C99 says I
should be able to get such "generic address" to PTR4 and dereference it. Where
can it be read that to access stack address space I should need a special
pointer? Where does it read I cannot derreference PTR4 if it points to stack?
Where can it be read that if I dereference PTR4 while its is pointing to stack
that pointer arithmetic will not be the same as any other?

>  In
> foo (int x, int y, int z)
> there are only x, y and z.  There is no array of parameters, the only
> "arrays" are that of implicit size 1 at locations &x, &y and &z which
> allows you to compute &x + 1 (but not dereference that pointer).

No, cdecl states that &x+1==&y, and that &x+2==&z. If a compiler is
cdecl-compliant I can trust this to be true.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (40 preceding siblings ...)
  2010-08-11 22:50 ` rogerio at rilhas dot com
@ 2010-08-11 22:51 ` rogerio at rilhas dot com
  2010-08-11 22:52 ` rogerio at rilhas dot com
                   ` (15 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:51 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2178 bytes --]



------- Comment #42 from rogerio at rilhas dot com  2010-08-11 22:51 -------
> It doesn't make it an array in the C sense.

What is an array in the C sense? Isn't it a sequence of entries? Is there any
other concept to go along with it that allows PTR4 to be set to any other value
than X? If so, where did you read it? I read in C99 that a pointer is simply a
variable that contains an address, and that C doesn't navigate "arrays in the C
sense" in anyway diferently than with "simple pointers". Do you have a C99
section that shows a distinction significant to this issue?

> &X gives you an address of X which happens to be on the stack.  Following
> parameters happen to be in adjacent stack slots.  Still C does not give
> you a way to access adjacent parameters by doing pointer arithmetic on
> &X.

Can you explain then how &X gets the format parameter from the stack and X[1]
doesn't get the next adjacent entry on the stack? Note that C99 is pretty clear
about the fact that X[1] will access bytes 4 to 7 after X. Can you backup your
claim with C99 or any other reference besides your personal interpretation?

> &X does _not_ get you access to anything like a "stack" as there is
> no such concept in the C language.

No problem. I don«t want PTR4 to be a specific "pointer to stack", I want it to
be a "general pointer to memory". I don«t need more than that and C99 says I
should be able to get such "generic address" to PTR4 and dereference it. Where
can it be read that to access stack address space I should need a special
pointer? Where does it read I cannot derreference PTR4 if it points to stack?
Where can it be read that if I dereference PTR4 while its is pointing to stack
that pointer arithmetic will not be the same as any other?

>  In
> foo (int x, int y, int z)
> there are only x, y and z.  There is no array of parameters, the only
> "arrays" are that of implicit size 1 at locations &x, &y and &z which
> allows you to compute &x + 1 (but not dereference that pointer).

No, cdecl states that &x+1==&y, and that &x+2==&z. If a compiler is
cdecl-compliant I can trust this to be true.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (41 preceding siblings ...)
  2010-08-11 22:51 ` rogerio at rilhas dot com
@ 2010-08-11 22:52 ` rogerio at rilhas dot com
  2010-08-11 22:53 ` rogerio at rilhas dot com
                   ` (14 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:52 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2178 bytes --]



------- Comment #43 from rogerio at rilhas dot com  2010-08-11 22:52 -------
> It doesn't make it an array in the C sense.

What is an array in the C sense? Isn't it a sequence of entries? Is there any
other concept to go along with it that allows PTR4 to be set to any other value
than X? If so, where did you read it? I read in C99 that a pointer is simply a
variable that contains an address, and that C doesn't navigate "arrays in the C
sense" in anyway diferently than with "simple pointers". Do you have a C99
section that shows a distinction significant to this issue?

> &X gives you an address of X which happens to be on the stack.  Following
> parameters happen to be in adjacent stack slots.  Still C does not give
> you a way to access adjacent parameters by doing pointer arithmetic on
> &X.

Can you explain then how &X gets the format parameter from the stack and X[1]
doesn't get the next adjacent entry on the stack? Note that C99 is pretty clear
about the fact that X[1] will access bytes 4 to 7 after X. Can you backup your
claim with C99 or any other reference besides your personal interpretation?

> &X does _not_ get you access to anything like a "stack" as there is
> no such concept in the C language.

No problem. I don«t want PTR4 to be a specific "pointer to stack", I want it to
be a "general pointer to memory". I don«t need more than that and C99 says I
should be able to get such "generic address" to PTR4 and dereference it. Where
can it be read that to access stack address space I should need a special
pointer? Where does it read I cannot derreference PTR4 if it points to stack?
Where can it be read that if I dereference PTR4 while its is pointing to stack
that pointer arithmetic will not be the same as any other?

>  In
> foo (int x, int y, int z)
> there are only x, y and z.  There is no array of parameters, the only
> "arrays" are that of implicit size 1 at locations &x, &y and &z which
> allows you to compute &x + 1 (but not dereference that pointer).

No, cdecl states that &x+1==&y, and that &x+2==&z. If a compiler is
cdecl-compliant I can trust this to be true.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (42 preceding siblings ...)
  2010-08-11 22:52 ` rogerio at rilhas dot com
@ 2010-08-11 22:53 ` rogerio at rilhas dot com
  2010-08-11 22:54 ` rogerio at rilhas dot com
                   ` (13 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:53 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2328 bytes --]



------- Comment #44 from rogerio at rilhas dot com  2010-08-11 22:53 -------
(In reply to comment #36)
> (In reply to comment #35)
> > (In reply to comment #33)



> It doesn't make it an array in the C sense.

What is an array in the C sense? Isn't it a sequence of entries? Is there any
other concept to go along with it that allows PTR4 to be set to any other value
than X? If so, where did you read it? I read in C99 that a pointer is simply a
variable that contains an address, and that C doesn't navigate "arrays in the C
sense" in anyway diferently than with "simple pointers". Do you have a C99
section that shows a distinction significant to this issue?

> &X gives you an address of X which happens to be on the stack.  Following
> parameters happen to be in adjacent stack slots.  Still C does not give
> you a way to access adjacent parameters by doing pointer arithmetic on
> &X.

Can you explain then how &X gets the format parameter from the stack and X[1]
doesn't get the next adjacent entry on the stack? Note that C99 is pretty clear
about the fact that X[1] will access bytes 4 to 7 after X. Can you backup your
claim with C99 or any other reference besides your personal interpretation?

> &X does _not_ get you access to anything like a "stack" as there is
> no such concept in the C language.

No problem. I don«t want PTR4 to be a specific "pointer to stack", I want it to
be a "general pointer to memory". I don«t need more than that and C99 says I
should be able to get such "generic address" to PTR4 and dereference it. Where
can it be read that to access stack address space I should need a special
pointer? Where does it read I cannot derreference PTR4 if it points to stack?
Where can it be read that if I dereference PTR4 while its is pointing to stack
that pointer arithmetic will not be the same as any other?

>  In
> foo (int x, int y, int z)
> there are only x, y and z.  There is no array of parameters, the only
> "arrays" are that of implicit size 1 at locations &x, &y and &z which
> allows you to compute &x + 1 (but not dereference that pointer).

No, cdecl states that &x+1==&y, and that &x+2==&z. If a compiler is
cdecl-compliant I can trust this to be true.

(sorry for the dupplication, I'm getting a lot of collisions)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (44 preceding siblings ...)
  2010-08-11 22:54 ` rogerio at rilhas dot com
@ 2010-08-11 22:54 ` rogerio at rilhas dot com
  2010-08-11 22:55 ` rogerio at rilhas dot com
                   ` (11 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:54 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #46 from rogerio at rilhas dot com  2010-08-11 22:54 -------
(In reply to comment #42)

(please disregard this duplication)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (43 preceding siblings ...)
  2010-08-11 22:53 ` rogerio at rilhas dot com
@ 2010-08-11 22:54 ` rogerio at rilhas dot com
  2010-08-11 22:54 ` rogerio at rilhas dot com
                   ` (12 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:54 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #45 from rogerio at rilhas dot com  2010-08-11 22:54 -------
(In reply to comment #43)

(please disregard this duplication)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (45 preceding siblings ...)
  2010-08-11 22:54 ` rogerio at rilhas dot com
@ 2010-08-11 22:55 ` rogerio at rilhas dot com
  2010-08-11 22:58 ` pinskia at gcc dot gnu dot org
                   ` (10 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 22:55 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #47 from rogerio at rilhas dot com  2010-08-11 22:55 -------
(In reply to comment #41)

(please disregard this duplication)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (46 preceding siblings ...)
  2010-08-11 22:55 ` rogerio at rilhas dot com
@ 2010-08-11 22:58 ` pinskia at gcc dot gnu dot org
  2010-08-11 23:22 ` rogerio at rilhas dot com
                   ` (9 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2010-08-11 22:58 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #48 from pinskia at gcc dot gnu dot org  2010-08-11 22:58 -------
>No, cdecl states that &x+1==&y, and that &x+2==&z.

Maybe the ABI says that but that does not mean you can access "&x + 1" to get
to &y at least in a "standard" defined way.  That is the whole point of it
acting as it was an array of size 1.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (47 preceding siblings ...)
  2010-08-11 22:58 ` pinskia at gcc dot gnu dot org
@ 2010-08-11 23:22 ` rogerio at rilhas dot com
  2010-08-11 23:43 ` rogerio at rilhas dot com
                   ` (8 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 23:22 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #49 from rogerio at rilhas dot com  2010-08-11 23:22 -------
(In reply to comment #40)
> (In reply to comment #39)
> > (In reply to comment #37)

> Why do you think GCC makes it the address of a copy?

Well, the first observation was dumpung the memory around the returned address
to see that the other parameters were not there.

The second observation was to see that the original object pushed by the caller
of direct_format was writen to an address which was not the one obtained in
"format_indirect".

Both are strong indicators. The first because I see the disassembly showing a
sequence of pushes for all parameters (hence, knowing x86, I trust they will be
adjacent although I can't check individual movements because I was unable to
trace individual assenbly instructions, but I checked the stack address after
the pushes and they are all sequential in memory). These parameters are never
changed in the stack, and keep adjacent all the time. So, accessing
"format_address" should reveal them.

The second is very difficult to observe in compiled code because any access to
"&format" before passing it as a parameter to "format_indirect" seems to fix
the problem (this is the basis for my workaround). However, I was able to
hardcode some printf's to locations where I knew the variables would be and
observe the results: the pushed parameters are kept adjacent, but the
address_format is somewhere else. My guess is that it is pointing to the "rom"
address where the string is stored in the executable, but I cannot be sure.


> You are wrong here.  The next paragraph, 6.5.6/8, explains that,
> "... otherwise the behavior is undefined.  If the result points one past
> the last element of the array object, it shall not be used as the operator
> of a unary * operator that is evaluated.".  Where I point you to
> 6.5.3.2/3 if you now claim that x[2] isn't invoking the unary * operator.

You are the ones saying that char** format_address is equivalent to a 1-entry
array. I have stated often that the array to which PTR4 points is an array of 4
entries, backed by cdecl.

But if your interpretation is that access to X+4 fails because the behaviour is
undefined because GCC generates code as that for a 1-entry array at address X,
and then generates some code to make accesses to address X+4 or X+8 (and so on)
fail, then no problem: just have GCC return the correct address X and I'll do
the accesses in assembly where I can trust what happens when I access X+4.

Note that your argument (of undefined behaviour) is only valid for declared
arrays, which I still think is not the case here. Or, at least, it points to a
4-entry array.

Also note that your argument does not backup the claim why GCC can return a
wrong address for &format. I also believe that you know that if GCC did return
the original address X on the stack then the "undefined" behaviour of [X+1]
would be to return the 4 bytes at X+4 without any problem, right? Or does GCC
generate specific code to make this memory access fail?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (48 preceding siblings ...)
  2010-08-11 23:22 ` rogerio at rilhas dot com
@ 2010-08-11 23:43 ` rogerio at rilhas dot com
  2010-08-12  2:08 ` rogerio at rilhas dot com
                   ` (7 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-11 23:43 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2478 bytes --]



------- Comment #50 from rogerio at rilhas dot com  2010-08-11 23:43 -------
(In reply to comment #48)
> >No, cdecl states that &x+1==&y, and that &x+2==&z.
> Maybe the ABI says that but that does not mean you can access "&x + 1" to get
> to &y at least in a "standard" defined way.  That is the whole point of it
> acting as it was an array of size 1.

Please note what you are saying. You mean that if, under GCC, I write some code
like:

void func_anything(void) {
char** PTR4=random_anywhere_in_valid_user_space_including_stack();
char* a=PTR4[0];
char* b=PTR4[1];
char* c=PTR4[2];
char* d=PTR4[3];
}

Are you telling me that GCC will not generate code to get propper values for
"b", "c", and "d" because reading past "a" is undefined? Note that the random
function does not define an "array in the C sense", it just returns a pointer
no different than "format_address".

The randomizer could, in fact, by something like
my_malloc_hand_crafted_with_no_relation_to_malloc_and_allocating_memory_directly_from_the_os()...
are you saying I would not be able to predictably access any of its bytes
(since it would not be related to an array of bytes "in the C sense"?

Now instead of a randomizer or a my_malloc I just called
get_random_address_exclusivelly_in_stack_space(), would access fail then?

And if instead I just called:

func foo(int x, int y, int z) {
int* PTR4=get_random_address_from_triplet(&x, &y, &z);
int new_var=*PTR4;
}

Would it fail here for new_var? If not, I could just write something like:

func foo(int x, int y, int z) {
int* PTR4_x=get_random_address_from_triplet_but_make_sure_its_x(&x, &y, &z);
int new_x=*PTR4_x;
int* PTR4_y=get_random_address_from_triplet_but_make_sure_its_y(&x, &y, &z);
int new_y=*PTR4_y;
int* PTR4_z=get_random_address_from_triplet_but_make_sure_its_z(&x, &y, &z);
int new_z=*PTR4_z;
}

Would this work? I'm not sure where this conversation is going to, but if this
code worked I could be a pretty good workaround for my indirect format. It must
work, right, I don't know which part of C99 says is, but if it didn«t work then
GCC would be useless and we know it is not.

So, the only possible conclusion is that "format_address" does not behave as a
1-entry array, because all these examples would lead to undefined results, and
so it must, in the very least, correspond to a 4-entry array (because I know I
can read the RAM locations with code generated by GCC).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (49 preceding siblings ...)
  2010-08-11 23:43 ` rogerio at rilhas dot com
@ 2010-08-12  2:08 ` rogerio at rilhas dot com
  2010-08-12  2:10 ` rogerio at rilhas dot com
                   ` (6 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12  2:08 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #51 from rogerio at rilhas dot com  2010-08-12 02:08 -------
Given all that we have established in our conversation I think I can now
demonstrate the bug easily.

The entry to the "format_direct" call (in the main function, just before
entering the "format_direct" function) disassembles to this (using
Code::Blocks, I've added comments):

0x80484de       mov    DWORD PTR [esp+0x10],0x80485f0 // __TIME__
0x80484e6       mov    DWORD PTR [esp+0xc],0x80485f9 // __DATE__
0x80484ee       mov    DWORD PTR [esp+0x8],0x8048605 // format string
0x80484f6       mov    DWORD PTR [esp+0x4],0x3e8 // sizeof(buffer)
0x80484fe       lea    eax,[ebp-0x3f0]
0x8048504       mov    DWORD PTR [esp],eax // buffer
0x8048507       call   0x8048460 <format_direct(char*, int, char const*, ...)>

At this point the $esp is 0xbfaeef00. So, the correct value for &format (as
defined in C99) is:

esp+8 = 0xbfaeef08

Reading that memory address after the "mov"'s I find 0x8048605 (format string).
The 0xbfaeef08 is the value I've been calling X and the value I will expect to
be passed to "format_indirect".

Reading the following address (+4) I see 0x80485f9 (date), and reading the next
(+8) I see there 0x80485f0 (time). They are all packed together as expected by
the cdecl ABI. Snapshot-2 (which I will send you after this message) shows this
(after the "mov"'s).

After entering "format_direct", I inserted the line:

char buffer[1000]; buffer[0]=0;

Without this line the compiler generates correct code, but with it if manifests
the bug. Just before calling "format_indirect", the disassembly is this (also
with comments):

0x804848d       lea    eax,[ebp-0x3f8]
0x8048493       mov    DWORD PTR [esp+0x8],eax  // &format
0x8048497       mov    eax,DWORD PTR [ebp+0xc]
0x804849a       mov    DWORD PTR [esp+0x4],eax  // dst_buffer_size_bytes
0x804849e       mov    eax,DWORD PTR [ebp-0x3f4]
0x80484a4       mov    DWORD PTR [esp],eax      // dst_buffer
0x80484a7       call   0x8048434 <format_indirect(char*, int, char const**)>

The $ebp contains 0xbfaeeef8, and so ebp+0x10 is 0xbfaeef08. That is the value
pushed onto the stack, and it is the correct &format which I called X
(Snapshot-3).

Next, entering "format_indirect" (Snapshot-4), the disassembly is this:

0x804843a       mov    eax,DWORD PTR [ebp+0x10]
0x804843d       mov    DWORD PTR [ebp-0x4],eax
0x8048440       mov    eax,DWORD PTR [ebp-0x4]
0x8048443       mov    eax,DWORD PTR [eax]
0x8048445       mov    DWORD PTR [ebp-0x8],eax
0x8048448       mov    eax,DWORD PTR [ebp-0x4]
0x804844b       add    eax,0x4
0x804844e       mov    eax,DWORD PTR [eax]
0x8048450       mov    DWORD PTR [ebp-0xc],eax
0x8048453       mov    eax,DWORD PTR [ebp-0x4]
0x8048456       add    eax,0x8
0x8048459       mov    eax,DWORD PTR [eax]
0x804845b       mov    DWORD PTR [ebp-0x10],eax

Unfortunately I have a really hard time debugging in Linux and it took me
almost an hour of trial and error (in between breakpoints not working, dumps
not working, the debugger hanging, repeating all addresses and retyping this
message because each time I run things endup at diferent places in memory,
etc.) to get all this information in one run, but I could not get the last
memory dump to work and I will not repeat the process again.

Instead, maybe you can go all out and believe me that the "format_address" is
wrong, as the watch window shows. The PTR4 will contain a "random value Y" of
0xbfaeeb00 which has no relation to the correct address X of 0xbfaeef08.

In fact, the watch window shows what is "around" PTR4, which looks to me like a
"rom" string table for the executable. It also shows that PTR4[0] returns the
correct string, but that PTR4[1] does not. If PTR4 were 0xbfaeef08 (as it
should by the definition of & in C99), then PTR4[1] would return the correct
string __DATE__ (nothing undefined in GCC's code behavior if the address PTR4
is correctly returned as X, as the disassembly shows the machine will just
access memory addresses after X).

With my compilation script I could not reproduce the problem (I don't know all
the options Code::Blocks uses, and so I did not change my compilation script to
use the same options), but that should not be necessary as my original
attachments and compilation script manifest the problem.

Maybe this bug doesn't affect many people, but it is a bug, and it affects me
(and my team). Probably even worse than that, it shows GCC is not C99 compliant
in the & operator.

Also, I hope this demonstration shows how futile it is for all of you to try to
argue that the problem in my code's portability, or that "format_address" is
like an array of 1 entry, or even that accessing PTR4[1] is undefined (the
disassembly shows it is not, the pointer arithmetic and no boundary checking
defined in C99 are all good and applied in the generated code). I think it also
shows that maybe you should have believed me in the first place instead of just
dismissing my claims as forms of "non-conformity". I still don't think this
should have required such a demonstration effort on my part.

I think this settles it, right? I hope so, I'm anxious to read your replies
hoping that maybe you recognize this as a bug and maybe decide to fix it (hope
is a very powerful thing!).

Thanks!


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (50 preceding siblings ...)
  2010-08-12  2:08 ` rogerio at rilhas dot com
@ 2010-08-12  2:10 ` rogerio at rilhas dot com
  2010-08-12  2:11 ` rogerio at rilhas dot com
                   ` (5 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12  2:10 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #52 from rogerio at rilhas dot com  2010-08-12 02:09 -------
Created an attachment (id=21462)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21462&action=view)
Snapshot 1 - Breakpoint before calling "format_direct"


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (51 preceding siblings ...)
  2010-08-12  2:10 ` rogerio at rilhas dot com
@ 2010-08-12  2:11 ` rogerio at rilhas dot com
  2010-08-12  2:12 ` rogerio at rilhas dot com
                   ` (4 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12  2:11 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #53 from rogerio at rilhas dot com  2010-08-12 02:10 -------
Created an attachment (id=21463)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21463&action=view)
Snapshot 2 - Inside "format_direct" to show cdecl ABI parameter packing


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (52 preceding siblings ...)
  2010-08-12  2:11 ` rogerio at rilhas dot com
@ 2010-08-12  2:12 ` rogerio at rilhas dot com
  2010-08-12  2:13 ` rogerio at rilhas dot com
                   ` (3 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12  2:12 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #54 from rogerio at rilhas dot com  2010-08-12 02:12 -------
Created an attachment (id=21464)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21464&action=view)
Snapshot 3 - Breakpoint before calling "format_indirect" (showing dump for
$ebp+0x10)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (53 preceding siblings ...)
  2010-08-12  2:12 ` rogerio at rilhas dot com
@ 2010-08-12  2:13 ` rogerio at rilhas dot com
  2010-08-12  8:20 ` jakub at gcc dot gnu dot org
                   ` (2 subsequent siblings)
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12  2:13 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #55 from rogerio at rilhas dot com  2010-08-12 02:12 -------
Created an attachment (id=21465)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=21465&action=view)
Snapshot 4 - Showing incorrect value for PTR4


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (54 preceding siblings ...)
  2010-08-12  2:13 ` rogerio at rilhas dot com
@ 2010-08-12  8:20 ` jakub at gcc dot gnu dot org
  2010-08-12 10:17 ` rogerio at rilhas dot com
  2010-08-12 10:18 ` paolo dot carlini at oracle dot com
  57 siblings, 0 replies; 59+ messages in thread
From: jakub at gcc dot gnu dot org @ 2010-08-12  8:20 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #56 from jakub at gcc dot gnu dot org  2010-08-12 08:20 -------
Please stop wasting your and GCC developers time.  As several people have
explained, your code triggers undefined behavior in C/C++, so it can do
anything at runtime.  The fact that it happens to work as you expect with some
compilers doesn't mean anything.  If you choose to program in C (or C++), you
just need to follow the standard.  GCC bugzilla is for reporting GCC bugs, not
for learning programming languages, look for various C forums instead.


-- 

jakub at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (55 preceding siblings ...)
  2010-08-12  8:20 ` jakub at gcc dot gnu dot org
@ 2010-08-12 10:17 ` rogerio at rilhas dot com
  2010-08-12 10:18 ` paolo dot carlini at oracle dot com
  57 siblings, 0 replies; 59+ messages in thread
From: rogerio at rilhas dot com @ 2010-08-12 10:17 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #57 from rogerio at rilhas dot com  2010-08-12 10:16 -------
(In reply to comment #56)
> Please stop wasting your and GCC developers time.  As several people have
> explained, your code triggers undefined behavior in C/C++, so it can do
> anything at runtime.  The fact that it happens to work as you expect with some
> compilers doesn't mean anything.  If you choose to program in C (or C++), you
> just need to follow the standard.  GCC bugzilla is for reporting GCC bugs, not
> for learning programming languages, look for various C forums instead.

I've clearly shown the bug in my commment #51. It is a bug in the address
operator. C99 says GCC shouldn't be doing that. The &format is not undefined
behavior. In comment #36 Richard Guenther agrees that &X should return the
stack address. GCC is not doing that. Please open your eyes and understand
this. It is simple. I believe you all have the brain power to understand at
least that. If you just forget all the rest and focus on &X you'll see GCC has
a bug. If you fix it I can then handle the rest on my own, thank you, no need
for all your rants about standards. You are the ones who shouldn't be wasting
my time like this.


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [Bug c++/45249] Indirect variable parameters sometimes cause segmentation fault
  2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
                   ` (56 preceding siblings ...)
  2010-08-12 10:17 ` rogerio at rilhas dot com
@ 2010-08-12 10:18 ` paolo dot carlini at oracle dot com
  57 siblings, 0 replies; 59+ messages in thread
From: paolo dot carlini at oracle dot com @ 2010-08-12 10:18 UTC (permalink / raw)
  To: gcc-bugs



------- Comment #58 from paolo dot carlini at oracle dot com  2010-08-12 10:18 -------
.


-- 

paolo dot carlini at oracle dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249


^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2010-08-12 10:18 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-10 21:55 [Bug c++/45249] New: Indirect variable parameters sometimes cause segmentation fault rogerio at rilhas dot com
2010-08-10 22:03 ` [Bug c++/45249] " rogerio at rilhas dot com
2010-08-10 22:04 ` rogerio at rilhas dot com
2010-08-10 22:04 ` rogerio at rilhas dot com
2010-08-10 22:07 ` pinskia at gcc dot gnu dot org
2010-08-10 22:33 ` rogerio at rilhas dot com
2010-08-10 22:36 ` rogerio at rilhas dot com
2010-08-10 23:08 ` pinskia at gcc dot gnu dot org
2010-08-11  0:55 ` rogerio at rilhas dot com
2010-08-11  0:58 ` pinskia at gcc dot gnu dot org
2010-08-11  1:57 ` rogerio at rilhas dot com
2010-08-11  3:52 ` pinskia at gcc dot gnu dot org
2010-08-11 11:21 ` rogerio at rilhas dot com
2010-08-11 11:21 ` rogerio at rilhas dot com
2010-08-11 11:22 ` rogerio at rilhas dot com
2010-08-11 11:37 ` rguenth at gcc dot gnu dot org
2010-08-11 11:41 ` rguenth at gcc dot gnu dot org
2010-08-11 11:55 ` redi at gcc dot gnu dot org
2010-08-11 13:12 ` rogerio at rilhas dot com
2010-08-11 14:10 ` redi at gcc dot gnu dot org
2010-08-11 16:11 ` matz at gcc dot gnu dot org
2010-08-11 17:04 ` rogerio at rilhas dot com
2010-08-11 17:15 ` rogerio at rilhas dot com
2010-08-11 17:49 ` pinskia at gcc dot gnu dot org
2010-08-11 17:57 ` redi at gcc dot gnu dot org
2010-08-11 19:51 ` rogerio at rilhas dot com
2010-08-11 19:54 ` pinskia at gcc dot gnu dot org
2010-08-11 20:04 ` rogerio at rilhas dot com
2010-08-11 20:07 ` rogerio at rilhas dot com
2010-08-11 20:33 ` rguenth at gcc dot gnu dot org
2010-08-11 20:58 ` rogerio at rilhas dot com
2010-08-11 21:02 ` pinskia at gcc dot gnu dot org
2010-08-11 21:12 ` rogerio at rilhas dot com
2010-08-11 21:16 ` pinskia at gcc dot gnu dot org
2010-08-11 21:27 ` redi at gcc dot gnu dot org
2010-08-11 22:17 ` rogerio at rilhas dot com
2010-08-11 22:27 ` rguenth at gcc dot gnu dot org
2010-08-11 22:31 ` rguenth at gcc dot gnu dot org
2010-08-11 22:35 ` rogerio at rilhas dot com
2010-08-11 22:37 ` rogerio at rilhas dot com
2010-08-11 22:48 ` rguenth at gcc dot gnu dot org
2010-08-11 22:50 ` rogerio at rilhas dot com
2010-08-11 22:51 ` rogerio at rilhas dot com
2010-08-11 22:52 ` rogerio at rilhas dot com
2010-08-11 22:53 ` rogerio at rilhas dot com
2010-08-11 22:54 ` rogerio at rilhas dot com
2010-08-11 22:54 ` rogerio at rilhas dot com
2010-08-11 22:55 ` rogerio at rilhas dot com
2010-08-11 22:58 ` pinskia at gcc dot gnu dot org
2010-08-11 23:22 ` rogerio at rilhas dot com
2010-08-11 23:43 ` rogerio at rilhas dot com
2010-08-12  2:08 ` rogerio at rilhas dot com
2010-08-12  2:10 ` rogerio at rilhas dot com
2010-08-12  2:11 ` rogerio at rilhas dot com
2010-08-12  2:12 ` rogerio at rilhas dot com
2010-08-12  2:13 ` rogerio at rilhas dot com
2010-08-12  8:20 ` jakub at gcc dot gnu dot org
2010-08-12 10:17 ` rogerio at rilhas dot com
2010-08-12 10:18 ` paolo dot carlini at oracle dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).