  Despite extensive testing and correctness certification of their functional
semantics, a number of compiler optimizations have been shown to violate
security guarantees implemented in source code. While prior work has shed light
on how such optimizations may introduce semantic security weaknesses into
programs, there remains a significant knowledge gap concerning the impacts of
compiler optimizations on non-semantic properties with security implications.
In particular, little is currently known about how code generation and
optimization decisions made by the compiler affect the availability and utility
of reusable code segments called gadgets required for implementing code reuse
attack methods such as return-oriented programming.
  In this paper, we bridge this gap through a study of the impacts of compiler
optimization on code reuse gadget sets. We analyze and compare 1,187 variants
of 20 different benchmark programs built with two production compilers (GCC and
Clang) to determine how their optimization behaviors affect the code reuse
gadget sets present in program variants with respect to both quantitative and
qualitative metrics. Our study exposes an important and unexpected problem;
compiler optimizations introduce new gadgets at a high rate and produce code
containing gadget sets that are generally more useful to an attacker than those
in unoptimized code. Using differential binary analysis, we identify several
undesirable behaviors at the root of this phenomenon. In turn, we propose and
evaluate several strategies to mitigate these behaviors. In particular, we show
that post-production binary recompilation can effectively mitigate these
behaviors with negligible performance impacts, resulting in optimized code with
significantly smaller and less useful gadget sets.
