From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750965AbdAPOey convert rfc822-to-8bit (ORCPT ); Mon, 16 Jan 2017 09:34:54 -0500 Received: from smtp-out6.electric.net ([192.162.217.181]:62655 "EHLO smtp-out6.electric.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750855AbdAPOex (ORCPT ); Mon, 16 Jan 2017 09:34:53 -0500 From: David Laight To: "'Anton Blanchard'" , "behanw@converseincode.com" , "ying.huang@intel.com" , "a.p.zijlstra@chello.nl" , "akpm@linux-foundation.org" , "oleg@redhat.com" , Segher Boessenkool , "mingo@elte.hu" CC: "linuxppc-dev@lists.ozlabs.org" , "linux-kernel@vger.kernel.org" Subject: RE: llist code relies on undefined behaviour, upsets llvm/clang Thread-Topic: llist code relies on undefined behaviour, upsets llvm/clang Thread-Index: AQHSb3ekU9wZT0rSBEC5iDjqLmUfBKE7KTVA Date: Mon, 16 Jan 2017 14:34:43 +0000 Message-ID: <063D6719AE5E284EB5DD2968C1650D6DB0264AA5@AcuExch.aculab.com> References: <20170116083600.47175073@kryten> In-Reply-To: <20170116083600.47175073@kryten> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.202.99.200] Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 8BIT MIME-Version: 1.0 X-Outbound-IP: 213.249.233.130 X-Env-From: David.Laight@ACULAB.COM X-Proto: esmtps X-Revdns: X-HELO: AcuExch.aculab.com X-TLS: TLSv1:AES128-SHA:128 X-Authenticated_ID: X-PolicySMART: 3396946, 3397078 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Anton Blanchard > Sent: 15 January 2017 21:36 > I was debugging a hang on a ppc64le kernel built with clang, and it > looks to be undefined behaviour with pointer wrapping in the llist code. > > A test case is below. llist_for_each_entry() does container_of() on a > NULL pointer, which wraps our pointer negative, then adds the same > offset back in and expects to get back to NULL. Unfortunately clang > decides that this can never be NULL and optimises it into an infinite > loop. ... > #define llist_for_each_entry(pos, node, member) \ > for ((pos) = llist_entry((node), typeof(*(pos)), member); \ > &(pos)->member != NULL; \ > (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member)) Maybe the above could be rewritten as (untested): for ((pos) = NULL; (!(pos) ? (node) : ((pos)->member.next) || (pos) = 0) && \ (((pos) = !(pos) ? llist_entry((node), typeof(*(pos)), member) \ : llist_entry((pos)->member.next, typeof(*(pos)), member)),1); ) Provided the compiler assumes that the loop body is never executed with 'pos == 0' it should generate the same code. David From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out6.electric.net (smtp-out6.electric.net [192.162.217.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3v2G3L1QHvzDqSQ for ; Tue, 17 Jan 2017 01:34:53 +1100 (AEDT) From: David Laight To: 'Anton Blanchard' , "behanw@converseincode.com" , "ying.huang@intel.com" , "a.p.zijlstra@chello.nl" , "akpm@linux-foundation.org" , "oleg@redhat.com" , Segher Boessenkool , "mingo@elte.hu" CC: "linuxppc-dev@lists.ozlabs.org" , "linux-kernel@vger.kernel.org" Subject: RE: llist code relies on undefined behaviour, upsets llvm/clang Date: Mon, 16 Jan 2017 14:34:43 +0000 Message-ID: <063D6719AE5E284EB5DD2968C1650D6DB0264AA5@AcuExch.aculab.com> References: <20170116083600.47175073@kryten> In-Reply-To: <20170116083600.47175073@kryten> Content-Type: text/plain; charset="Windows-1252" MIME-Version: 1.0 List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Anton Blanchard > Sent: 15 January 2017 21:36 > I was debugging a hang on a ppc64le kernel built with clang, and it > looks to be undefined behaviour with pointer wrapping in the llist code. >=20 > A test case is below. llist_for_each_entry() does container_of() on a > NULL pointer, which wraps our pointer negative, then adds the same > offset back in and expects to get back to NULL. Unfortunately clang > decides that this can never be NULL and optimises it into an infinite > loop. ... > #define llist_for_each_entry(pos, node, member) \ > for ((pos) =3D llist_entry((node), typeof(*(pos)), member); = \ > &(pos)->member !=3D NULL; = \ > (pos) =3D llist_entry((pos)->member.next, typeof(*(pos)), me= mber)) Maybe the above could be rewritten as (untested): for ((pos) =3D NULL; (!(pos) ? (node) : ((pos)->member.next) || (pos) =3D= 0) && \ (((pos) =3D !(pos) ? llist_entry((node), typeof(*(pos)), member) \ : llist_entry((pos)->member.next, typeof(*(pos)), member)),1); ) Provided the compiler assumes that the loop body is never executed with 'po= s =3D=3D 0' it should generate the same code. David