Hi Guys,
I just found an issue in kernel code and thought we must have a compilation warning for such cases.
Submitted a bug here:
https://bugs.launchpad.net/gcc-linaro/+bug/1064218
Problem description: -------------------------
When we have following declaration:
struct foo { char array[5]; .... };
And have a definition like:
struct foo foo_abc = { .array = "12345", };
Problem here is: size of array is 5 bytes and so we can actually add a string with four characters only to it, as '\0' will take an additional space.
But with my definition of foo_abc.. i had 5 characters + '\0'... that will make it 6 and that will overflow the array..
What will actually happen here? - compiler will not add '\0' at all? -or it will go outside of boundaries of array?
-- viresh
Viresh Kumar wrote:
When we have following declaration:
struct foo { char array[5]; .... };
And have a definition like:
struct foo foo_abc = { .array = "12345", };
Problem here is: size of array is 5 bytes and so we can actually add a string with four characters only to it, as '\0' will take an additional space.
But with my definition of foo_abc.. i had 5 characters + '\0'... that will make it 6 and that will overflow the array..
What will actually happen here?
- compiler will not add '\0' at all?
- or it will go outside of boundaries of array?
I think it will go outside of boundaries. You should avoid adding the \0 or redefine char array to hold up to 6 chars.
Regards
Hi,
Thanks for your quick response.
On 9 October 2012 13:39, davi@gnu.org wrote:
Viresh Kumar wrote:
When we have following declaration:
struct foo { char array[5]; .... };
And have a definition like:
struct foo foo_abc = { .array = "12345", };
Problem here is: size of array is 5 bytes and so we can actually add a string with four characters only to it, as '\0' will take an additional space.
But with my definition of foo_abc.. i had 5 characters + '\0'... that will make it 6 and that will overflow the array..
What will actually happen here?
- compiler will not add '\0' at all?
- or it will go outside of boundaries of array?
I think it will go outside of boundaries. You should avoid adding the \0 or redefine char array to hold up to 6 chars.
Ok. So it will overwrite whatever follows the memory of this struct if array is the last element in this struct.
struct foo { .... char array[5]; };
I am not adding '\0' in my string at all. Is this '\0' always added by compiler, even in above situation?
-- viresh
Viresh Kumar wrote:
struct foo { .... char array[5];
};
I am not adding '\0' in my string at all. Is this '\0' always added by compiler, even in above situation?
The compiler does not add the trailing '\0'. It is added only by the string manipulation functions, as for example sprintf.
Regards
[copy of my answer in your bug report]
Hello,
If you look at the assembly code generated by the compiler, you will see: foo_abc: .ascii "12345"
From the gas documentation:
`.ascii' expects zero or more string literals (*note Strings::) separated by commas. It assembles each string (with no automatic trailing zero byte) into consecutive addresses.
So, '\0' is NOT added at the end of the initializer.
If you change your initialization to "123456", GCC prints a warning: warning: initializer-string for array of chars is too long [enabled by default] warning: (near initialization for 'foo_abc.array') [enabled by default]
On 9 October 2012 09:53, Viresh Kumar viresh.kumar@linaro.org wrote:
Hi Guys,
I just found an issue in kernel code and thought we must have a compilation warning for such cases.
Submitted a bug here:
https://bugs.launchpad.net/gcc-linaro/+bug/1064218
Problem description:
When we have following declaration:
struct foo { char array[5]; .... };
And have a definition like:
struct foo foo_abc = { .array = "12345", };
Problem here is: size of array is 5 bytes and so we can actually add a string with four characters only to it, as '\0' will take an additional space.
But with my definition of foo_abc.. i had 5 characters + '\0'... that will make it 6 and that will overflow the array..
What will actually happen here?
- compiler will not add '\0' at all?
-or it will go outside of boundaries of array?
-- viresh
linaro-toolchain mailing list linaro-toolchain@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-toolchain
On 9 October 2012 13:47, Christophe Lyon christophe.lyon@linaro.org wrote:
[copy of my answer in your bug report]
Hello,
If you look at the assembly code generated by the compiler, you will see: foo_abc: .ascii "12345"
From the gas documentation: `.ascii' expects zero or more string literals (*note Strings::) separated by commas. It assembles each string (with no automatic trailing zero byte) into consecutive addresses.
So, '\0' is NOT added at the end of the initializer.
If you change your initialization to "123456", GCC prints a warning: warning: initializer-string for array of chars is too long [enabled by default] warning: (near initialization for 'foo_abc.array') [enabled by default]
Something new, At least for me :) This means code like below can break anytime :(
char foo1[4] = "test"; char foo2[4];
void mystrcpy(char *src, char *dst) { /* Well known strcpy implementation */ while (*dst++ = *src++); }
void main(void) { mystrcpy(foo1, foo2); printf("src: %s and dst: %s\n", foo1, foo2); }
As, nobody is guarantees that location next to foo1 is going to be '\0'?
-- viresh
On 9 October 2012 08:53, Viresh Kumar viresh.kumar@linaro.org wrote:
Hi Guys,
I just found an issue in kernel code and thought we must have a compilation warning for such cases.
Submitted a bug here:
https://bugs.launchpad.net/gcc-linaro/+bug/1064218
Problem description:
When we have following declaration:
struct foo { char array[5]; .... };
And have a definition like:
struct foo foo_abc = { .array = "12345", };
Problem here is: size of array is 5 bytes and so we can actually add a string with four characters only to it, as '\0' will take an additional space.
But with my definition of foo_abc.. i had 5 characters + '\0'... that will make it 6 and that will overflow the array..
What will actually happen here?
- compiler will not add '\0' at all?
-or it will go outside of boundaries of array?
This is what the C99 standard says:
An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
In your case, the array will be initialised with the numbers 1-5, the null terminator of the string literal is ignored. Initialisers like this are fairly common and well-defined by the spec, so warning about them would be wrong IMHO.
On 9 October 2012 17:13, Mans Rullgard mans.rullgard@linaro.org wrote:
This is what the C99 standard says:
An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
In your case, the array will be initialised with the numbers 1-5, the null terminator of the string literal is ignored. Initialisers like this are fairly common and well-defined by the spec, so warning about them would be wrong IMHO.
Ahh.. My fault actually. I knew this stuff for any other array type, like int. If you initialize few fields of array, then the remaining are initialized with zero automatically.
And the same will hold for this one too... Because ascii value of '\0' is 0, so all the fields array elements, except the ones explicitly initialized with values will get initialized with 0 or '\0'. That's why the mystrcpy() routine written earlier by me will work (only if RHS string size is smaller than array size :) )
So, there is no overflow here at all. '\0' is just not there for this string and so printf("%s", ...) can show unexpected results.
-- viresh
linaro-toolchain@lists.linaro.org