In x86, GCC generates the following instructions when it wants to call __stack_chk_fail
:
; start of the basic block
00000757 call sub_590 ; __stack_chk_fail@plt
0000075c add byte [ds:eax], al
0000075e add byte [ds:eax], al
; start point of another function
Similar behavior happens in ARM:
; start of the basic block
00001000 bl __stack_chk_fail@PLT
00001004 dd 0x0000309c ; data entry, NOT executable indeed!
In static analysis tools, when one wants to build a CFG, the CFG algorithm can't determine last instruction of the basic block which the __stack_chk_fails
is called in.
It's reasonable to have some sort of return instruction after calling __stack_chk_fail
to prevent CPU to execute instructions (or potentially data entries) which it shouldn't.
In these cases, CFG generator algorithm assumes it's a regular function call and continues traversing to another function's code (in the former example) or to data entries (in the later one) which is totally unwanted.
So, my question is why doesn't GCC insert a return (or branch) instruction at the end point of the basic block?