[RFC][Draft patch] Introduce IntegerSanitizer in GCC.

Maxim Ostapenko m.ostapenko@samsung.com
Mon Jul 4 11:13:00 GMT 2016


Hi!

Although in languages like C and C++ unsigned integer overflow reliably 
wraps around and well defined, sometimes it may indicate an error in 
code and lead to undesirable consequences and even security 
vulnerabilities 
(https://android-developers.blogspot.ru/2016/05/hardening-media-stack.html). 
Clang has corresponding '-fsanitize=unsigned-integer-overflow' option 
that may catch some of these errors (but misses some important cases 
such as pointers overflow), GCC has not and instruments only signed 
integer operations (S = S {+, -, *} S).

Although GCC has a nice framework for instrumenting even "mixed" binary 
operations (e.g. S = U + S) in middle end, implemented by Jakub some 
time ago (see expand_addsub_overflow, expand_mul_overflow etc in 
internal-fn.c), adding support for sanitizing unsigned and "mixed" 
binary operations seems to be quite problematic in terms of huge amount 
of false positive reports that may pop up in following cases:

1) Some code intentionally relies on overflows, e.g. when computing hash 
codes. Unfortunately, it seems that we cannot do anything with it on 
compiler side, programmer will need to do some filtering here by himself.

2) Unfortunately, it seems that C and C++ FEs don't provide suitable 
interfaces to get *LHS* real type when building binary expressions, so 
*build_binary_op* doesn't know about *LHS* real type and we can easily 
end up with false positive report e.g. in such code:

int
cmp (const char *s1, const char *s2)
{
   return strlen (s1) - strlen (s2);
}

because in gimple we would have something like this:

   unsigned int tmp, len1, len2;
   int result;
   .........
   tmp = len1 - len2;  <===== FP here if len1 < len2
   result = (int) tmp;
   return result;

3) GCC relies on unsigned integer overflows when constructing 
POINTER_PLUS expressions. We need a special treatment for this case, 
because it's quite common to have a negative offset from a given pointer 
and we don't want have false reports here.

This very draft patch (of course we would need more testcases, changelog 
entry etc) adds support for '-fsanitize=unsigned-integer-overflow' to 
GCC for PLUS, MINUS and MULT operations, extending its functionality to 
support pointers overflow and binary operations with different signess 
of theirs operands ("mixed" binary operations, say, S = U + S). It 
simply replaces all +, - and * by new ISAN_CHECK_{ADD, SUB, MUL} 
intrinsics in C and C++ FEs to be lowered later during intrinsics 
expansion. For example, if we have a + b expression, it would be 
replaced in FE by following call:

a + b -> ISAN_CHECK_ADD (a, b, a_unsiged_p, b_unsigned_p, result_unsigned_p)

where *a_unsiged_p* is 1 if *a* is unsigned and 0 otherwise. The same 
rule applies for *b_unsigned_p*. The *result_unsigned_p* value should 
reflect result type signess, but as mentioned in 2), we don't know it 
when building binary expression, so we can only guess it from arguments 
types and maybe change it (in a very hackish way) later (see 
*isan_maybe_change_ifn_sign_arg* function) in order to reduce number of 
FPs (in fact, these hacks can significantly reduce FPs ratio, ~ 30%). 
These values will be used in *expand_addsub_overflow* and 
*expand_mul_overflow* functions to compute overflow correctly.

This patch survives GCC bootstrap, I've also managed to build Firefox 
and Chromium with '-fsanitize=unsigned-integer-overflow' enabled. The 
tool found several bugs in opensource software:

1) Integer overflow when computing len parameter in "file" utility 
(http://bugs.gw.com/view.php?id=555)
2) Pointer overflow (nullptr - 1) in Google's skia library 
(https://bugs.chromium.org/p/skia/issues/detail?id=5415)
3) Unsigned integer overflow in HAL component in Firefox 
(https://bugzilla.mozilla.org/show_bug.cgi?id=1280514)

Is community interested in such a tool? Any feedback would be greatly 
appreciated, especially some points how we can figure out real result 
type for *LHS* of binary expressions in
*build_binary_op* in order to avoid unnecessary FPs and ugly hacks in FEs.

Thanks,
-Maxim
-------------- next part --------------
A non-text attachment was scrubbed...
Name: isan.diff
Type: text/x-diff
Size: 49134 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20160704/7a2df5d1/attachment.bin>


More information about the Gcc mailing list