On 04/17/2013 02:49 AM, Han Shen wrote:
+ if (flag_stack_protect == 3)
+ cpp_define (pfile, "__SSP_STRONG__=3");
if (flag_stack_protect == 2)
cpp_define (pfile, "__SSP_ALL__=2");
3 and 2 should be replaced by SPCT_FLAG_STRONG and SPCT_FLAG_ALL.
I define these SPCT_FLAG_XXX in cfgexpand.c locally, so they are not
visible to c-cppbuiltin.c, do you suggest define these inside
c-cppbuiltin.c also?
I see. Let's use the constants for now.
Indentation is off (unless both mail clients I tried are clobbering your
patch). I think the GNU coding style prohibits the braces around the
single-statement body of the outer 'for".
Done with indentation properly on and removed the braces. (GMail
composing window drops all the tabs when pasting... I have to use
Thunderbird to paste the patch. Hope it is right this time)
Thunderbird mangles patches as well, but I was able to repair the
damage. When using Thunderbird, please send the patch as a text file
attachment. You can put the changelog snippets at the beginning of the
file as well. This way, everything is sent out unchanged.
Can you make the conditional more similar to the comment, perhaps using a
switch statement on the value of the flag_stack_protect variable? That's
going to be much easier to read.
Re-coded. Now using 'switch-case'.
Thanks. I think the comment is now redundant because it matches the
code almost word-for-word. 8-)
No for 'struct-returning' functions. But I regard this not an issue ---
at the programming level, there is no way to get one's hand on the
address of a returned structure ---
struct Node foo();
struct Node *p = &foo(); // compiler error - lvalue required as
unary '&' operand.
C++ const references can bind to rvalues.
But I'm more worried about the interaction with the return value
optimization. Consider this C++ code:
struct S {
S();
int a;
int b;
int c;
int d;
int e;
};
void f1(int *);
S f2()
{
S s;
f1(&s.a);
return s;
}
S g2();
void g3()
{
S s = g2();
}
void g3b(const S&);
void g3b()
{
g3b(g2());
}
With your patch and -O2 -fstack-protector-strong, this generates the
following assembly:
.globl _Z2f2v
.type _Z2f2v, @function
_Z2f2v:
.LFB0:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
movq %rdi, %rbx
call _ZN1SC1Ev
movq %rbx, %rdi
call _Z2f1Pi
movq %rbx, %rax
popq %rbx
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE0:
.size _Z2f2v, .-_Z2f2v
.p2align 4,,15
.globl _Z2g3v
.type _Z2g3v, @function
_Z2g3v:
.LFB1:
.cfi_startproc
subq $40, %rsp
.cfi_def_cfa_offset 48
movq %rsp, %rdi
call _Z2g2v
addq $40, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1:
.size _Z2g3v, .-_Z2g3v
.p2align 4,,15
.globl _Z3g3bv
.type _Z3g3bv, @function
_Z3g3bv:
.LFB2:
.cfi_startproc
subq $40, %rsp
.cfi_def_cfa_offset 48
movq %rsp, %rdi
movq %fs:40, %rax
movq %rax, 24(%rsp)
xorl %eax, %eax
call _Z2g2v
movq %rsp, %rdi
call _Z3g3bRK1S
movq 24(%rsp), %rax
xorq %fs:40, %rax
jne .L9
addq $40, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 8
ret
.L9:
.cfi_restore_state
.p2align 4,,6
call __stack_chk_fail
.cfi_endproc
.LFE2:
.size _Z3g3bv, .-_Z3g3bv
Here, g3b() is correctly instrumented, and f2() does not need
instrumentation (because space for the returned object is not part of
the local frame). But an address on the stack escapes in g3() and is
used for the return value of the call to g2(). This requires
instrumentation, which is missing in this example.
I suppose this can be handled in a follow-up patch if necessary.
ChangeLog and patch below --
gcc/ChangeLog
2013-04-16 Han Shen <shen...@google.com>
* cfgexpand.c (record_or_union_type_has_array_p): Helper function
to check if a record or union contains an array field.
I think the GNU convention is to write only this:
* cfgexpand.c (record_or_union_type_has_array_p): New function.
(expand_used_vars): Add logic handling '-fstack-protector-strong'.
* common.opt (fstack-protector-all): New option.
Should be "fstack-protector-strong".
--
Florian Weimer / Red Hat Product Security Team