From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26361 invoked by alias); 26 Jul 2011 09:39:06 -0000 Received: (qmail 26350 invoked by uid 22791); 26 Jul 2011 09:39:06 -0000 X-SWARE-Spam-Status: No, hits=-0.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from smtp.fullrate.dk (HELO smtp.fullrate.dk) (90.185.1.42) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 26 Jul 2011 09:38:51 +0000 Received: from [192.168.1.33] (3604ds3-fb.0.fullrate.dk [90.184.27.253]) by smtp.fullrate.dk (Postfix) with ESMTP id 7FF919CFBA for ; Tue, 26 Jul 2011 11:38:52 +0200 (CEST) Message-ID: <4E2E8B12.1090204@agner.org> Date: Tue, 26 Jul 2011 09:39:00 -0000 From: Agner Fog User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20110624 Thunderbird/5.0 MIME-Version: 1.0 To: gcc-help@gcc.gnu.org Subject: Re: Is it OK that gcc optimizes away overflow check? References: <4E2B2B72.9050504@agner.org> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-IsSubscribed: yes Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org X-SW-Source: 2011-07/txt/msg00261.txt.bz2 On 25-07-2011 08:04, Ian Lance Taylor wrote: > It's reasonably straightforward to check for overflow of any operation > by doing the arithmetic in unsigned types. By definition of the > language standard, unsigned types wrap rather than overflow. I tried some more google search on this problem. It is quite common to check for overflow after the fact, so obviously many programmers are unaware of the problem. The safe solution is described in a recent CERT paper: https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow The CERT paper recommends this check for overflow before adding two signed integers on a 2's complement machine: |if| |( ((si1^si2) | (((si1^(~(si1^si2) & INT_MIN)) + si2)^si2)) >= 0) {| |||/* handle error condition */| |} ||else| |{| |||sum = si1 + si2;| |}| Now, imagine doing something like this before every +, -, *, /, etc. in your code! If this is necessary then the C/C++ language is useless. We are in deep trouble now and we desperately need a better solution. A security conscious programmer will typically replace an array with a SafeArray class with bounds checking. But even this will not work if the array index is the result of a calculation that can overflow, which almost all calculations can. Your suggestion to use __attribute__ ((optimize ("-fno-strict-overflow"))); was an excellent idea. Unfortunately it doesn't work. The compiler says: warning: Ć¢optimizeĆ¢ attribute directive ignored. We need to be constructive here. We want the optimizations, but we also want to check if the optimizations go wrong. I think the compiler should be able to generate warnings for every unsafe optimization, especially when removing a branch. The compiler generates a warning when optimizing away if (a+5 < a) but not when optimizing away if (abs(a)<0). Some compilers make a warning whenever optimizing away a branch, saying something like "warning: condition is always false". A branch that cannot be taken is quite likely to be the symptom of a logical error, so such a warning will be useful I think, and it would catch an overflow check that is optimized away. Would that generate too many warnings? That depends on the programming style, but in most cases I think it would be useful, and of course you can turn off the warnings.