This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Should structure with flexible array be allowed to be passed by value?


Pardon my intrusion on this thread, but if I ever coded anything so catastrophically hazardous, I'd want to at least be warned about it... if not slapped on the wrist and told "No No No No NO."

Structures with flexible array members must be created dynamically in order to allocate proper space for their contents and should, therefore, always be passed or returned by pointer such as any other dynamic data structure. With higher level languages encapsulating such hazards out of sight, it may appear to less experienced programmers as though passing variable length data structures by value were a legitimate operation. I believe that merits at least a warning, if possible, for such misconceived ideas.

The following code, by the way, does not emit any errors or warnings when compiled with gcc version 4.1.2.. I haven't tested with any more recent versions. I do understand that we can't protect everybody from every form of hazardous code, but because this was brought up, I figured something should be said.

- Brian Ellis

----- CODE SNIP -----

#include <stdlib.h>
#include <stdio.h>

struct dynamic
{
        int size;
        int array[];
};

void dont_do_this( struct dynamic wrong_answer )
{
        printf( "Now showing an array of %d wrong answers.\n", wrong_answer.size );
        
        int x;
        for( x=0; x<wrong_answer.size; x++ )
        {
                printf( "\t%d\n", wrong_answer.array[x] );
        }
}

void do_it_this_way( struct dynamic *pRightAnswer )
{
        printf( "Now showing an array of %d values.\n", pRightAnswer->size );

        int x;
        for( x=0; x<pRightAnswer->size; x++)
        {
                printf( "\t%d\n", pRightAnswer->array[x] );
        }
}

int main()
{
        struct dynamic * pBadness =  ((struct dynamic *) malloc( sizeof(int) * 3) );

        if( pBadness == NULL )
        {
                puts( "Failed to allocate memory.\n" );
                return -1;
        }

        pBadness->size = 2;
        pBadness->array[0] = 42;
        pBadness->array[1] = -42;

        dont_do_this( *pBadness );
        do_it_this_way( pBadness );

        return 0;
}

---- CODE SNIP ----



----- Original Message ----
From: H.J. Lu <hjl.tools@gmail.com>
To: Joseph S. Myers <joseph@codesourcery.com>
Cc: "gcc@gnu.org" <gcc@gnu.org>; discuss@x86-64.org
Sent: Tuesday, March 24, 2009 11:20:40 AM
Subject: Re: Should structure with flexible array be allowed to be passed by   value?

On Tue, Mar 24, 2009 at 8:16 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Tue, 24 Mar 2009, H.J. Lu wrote:
>
>> Should
>>
>> struct line {
>>        int length;
>>        char contents[0];
>>  };
>>
>> or
>>
>> struct line {
>>        int length;
>>        char contents[];
>>  };
>>
>> be allowed to be passed by value? If yes, how do you access the contents field?
>
> I see nothing about passing by value different from structure assignment,
> which ignores the flexible array member (see 6.7.2.1 paragraph 22 (in
> N1256) for an example stating this).  Although argument passing and return
> aren't strictly assignments, they generally act in the same way, so such a
> structure passed by value or used as a function return value loses the
> flexible array members in the process.  I suppose an optional warning for
> this might be useful.
>

How should be they passed on x86-64? psABI isn't clear and gcc isn't consistent
with char contents[0] vs char contents[].


-- 
H.J.



      
#include <stdlib.h>
#include <stdio.h>

struct dynamic
{
	int size;
	int bad[];
};

int dont_do_this( struct dynamic wrong_answer )
{
	return wrong_answer.bad[1];
}

int main()
{
	struct dynamic * pBadness =  ((struct dynamic *) malloc( sizeof(int) + 4) );

	if( pBadness == NULL )
	{
		puts( "Failed to allocate memory.\n" );
		return -1;
	}

	pBadness->bad[0] = 42;

	int not42 = dont_do_this( *pBadness );

	printf( "It let me do something very bad and gave me %d as the answer.\n", not42 );
	return 0;
}


#include <stdlib.h>
#include <stdio.h>

struct dynamic
{
	int size;
	int bad[];
};

void dont_do_this( struct dynamic wrong_answer )
{
	printf( "Now showing an array of %d wrong answers.\n", wrong_answer.size );
	
	int x;
	for( x=0; x<wrong_answer.size; x++ )
	{
		printf( "\t%d\n", wrong_answer.bad[x] );
	}
}

void do_it_this_way( struct dynamic *pRightAnswer )
{
	printf( "Now showing an array of %d values.\n", pRightAnswer->size );

	int x;
	for( x=0; x<pRightAnswer->size; x++)
	{
		printf( "\t%d\n", pRightAnswer->bad[x] );
	}
}

int main()
{
	struct dynamic * pBadness =  ((struct dynamic *) malloc( sizeof(int) * 3) );

	if( pBadness == NULL )
	{
		puts( "Failed to allocate memory.\n" );
		return -1;
	}

	pBadness->size = 2;
	pBadness->bad[0] = 42;
	pBadness->bad[1] = -42;

	dont_do_this( *pBadness );
	do_it_this_way( pBadness );

	return 0;
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]