From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754155AbbGWWUP (ORCPT ); Thu, 23 Jul 2015 18:20:15 -0400 Received: from mail-wi0-f171.google.com ([209.85.212.171]:37202 "EHLO mail-wi0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754102AbbGWWUM (ORCPT ); Thu, 23 Jul 2015 18:20:12 -0400 Date: Fri, 24 Jul 2015 01:20:09 +0300 From: Alexey Dobriyan To: =?iso-8859-1?Q?J=F6rn?= Engel Cc: linux-kernel@vger.kernel.org, Yinghai Lu , Spencer Baugh Subject: Re: round_up integer underflow Message-ID: <20150723222008.GA1743@p183.telecom.by> References: <20150723180255.GA24876@Sligo.logfs.org> <20150723181030.GC24876@Sligo.logfs.org> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20150723181030.GC24876@Sligo.logfs.org> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jul 23, 2015 at 11:10:30AM -0700, Jörn Engel wrote: > On Thu, Jul 23, 2015 at 11:02:55AM -0700, Jörn Engel wrote: > > Spencer spotted something nasty in the round_up macro. We were > > wondering why round_up() worked differently from ALIGN. The only real > > difference between the two patterns is overflow behaviour. And both > > version are buggy when used for signed integer types, round_up will > > underflow on INT_MIN, ALIGN will overflow on INT_MAX. Since signed > > integer under/overflows are undefined, we might have subtle bugs lurking > > in the kernel. > > > > This example program produces a warning when compiling with gcc -O2 or > > higher. Clang doesn't warn. Compiled code behaves correctly with both > > compilers, but that is largely luck and the same compilers may create > > wrong behaviour if the surrounding code changes. > > > > #include > > #include > > > > #define __round_mask(x, y) ((__typeof__(x))((y)-1)) > > #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) > > #define round_down(x, y) ((x) & ~__round_mask(x, y)) > > > > int main(void) > > { > > int i, r = 8; > > > > for (i = INT_MIN; i; i++) { > > printf("%2x: %2x %2x\n", i, round_down(i, r), round_up(i, r)); > > } > > return 0; > > } > > > > I don't have a good answer yet. We could make round_up check for > > negative numbers, but I would prefer unconditional code that optimizes > > down to nothing. We could rewrite it in assembly, once for each > > architecture. > > > > Does anyone have better ideas? You can fix overflow issues but the ALIGN(INT_MAX, a) creating much smaller value is probably a bug anyway. It should BUG_ON or something (yes, I'm aware of recent memo). > #define round_up(x, y) (__typeof__(x)(__round_up((unsigned __typeof__(x)(x)), (y)))) ^^^^^^^^^^^^^^^^^^^ If only... :-( > I.e. cast x to the matching unsigned type where overflows are > well-defined, do the rounding, then cast the result back to the original > type.