From owner-svn-src-all@FreeBSD.ORG Fri Aug 15 22:36:43 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0F907FDE; Fri, 15 Aug 2014 22:36:43 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E3E252681; Fri, 15 Aug 2014 22:36:42 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s7FMagpe043436; Fri, 15 Aug 2014 22:36:42 GMT (envelope-from jilles@FreeBSD.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s7FMagUJ043433; Fri, 15 Aug 2014 22:36:42 GMT (envelope-from jilles@FreeBSD.org) Message-Id: <201408152236.s7FMagUJ043433@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jilles set sender to jilles@FreeBSD.org using -f From: Jilles Tjoelker Date: Fri, 15 Aug 2014 22:36:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r270029 - in head/bin/sh: . tests/expansion X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Aug 2014 22:36:43 -0000 Author: jilles Date: Fri Aug 15 22:36:41 2014 New Revision: 270029 URL: http://svnweb.freebsd.org/changeset/base/270029 Log: sh: Mask off shift distance (<< and >>) in arithmetic. In C, shift distances equal to or larger than the number of bits in the operand result in undefined behaviour. As part of eliminating undefined behaviour in arithmetic, mask off the distance like Java and JavaScript specify and C on x86 usually does. Assumption: conversion from unsigned to signed retains the two's complement bits. Assumption: uintmax_t has no padding bits. Added: head/bin/sh/tests/expansion/arith14.0 (contents, props changed) Modified: head/bin/sh/arith_yacc.c head/bin/sh/tests/expansion/Makefile Modified: head/bin/sh/arith_yacc.c ============================================================================== --- head/bin/sh/arith_yacc.c Fri Aug 15 21:35:31 2014 (r270028) +++ head/bin/sh/arith_yacc.c Fri Aug 15 22:36:41 2014 (r270029) @@ -139,9 +139,10 @@ static arith_t do_binop(int op, arith_t case ARITH_SUB: return (uintmax_t)a - (uintmax_t)b; case ARITH_LSHIFT: - return (uintmax_t)a << b; + return (uintmax_t)a << + ((uintmax_t)b & (sizeof(uintmax_t) * CHAR_BIT - 1)); case ARITH_RSHIFT: - return a >> b; + return a >> ((uintmax_t)b & (sizeof(uintmax_t) * CHAR_BIT - 1)); case ARITH_LT: return a < b; case ARITH_LE: Modified: head/bin/sh/tests/expansion/Makefile ============================================================================== --- head/bin/sh/tests/expansion/Makefile Fri Aug 15 21:35:31 2014 (r270028) +++ head/bin/sh/tests/expansion/Makefile Fri Aug 15 22:36:41 2014 (r270029) @@ -20,6 +20,7 @@ FILES+= arith10.0 FILES+= arith11.0 FILES+= arith12.0 FILES+= arith13.0 +FILES+= arith14.0 FILES+= assign1.0 FILES+= cmdsubst1.0 FILES+= cmdsubst2.0 Added: head/bin/sh/tests/expansion/arith14.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/expansion/arith14.0 Fri Aug 15 22:36:41 2014 (r270029) @@ -0,0 +1,40 @@ +# $FreeBSD$ +# Check that <> use the low bits of the shift count. + +if [ $((1<<16<<16)) = 0 ]; then + width=32 +elif [ $((1<<32<<32)) = 0 ]; then + width=64 +elif [ $((1<<64<<64)) = 0 ]; then + width=128 +elif [ $((1<<64>>64)) = 1 ]; then + # Integers are wider than 128 bits; assume arbitrary precision. + # Nothing to test here. + exit 0 +else + echo "Cannot determine integer width" + exit 2 +fi + +twowidth=$((width * 2)) +j=43 k=$((1 << (width - 2))) r=0 + +i=0 +while [ $i -lt $twowidth ]; do + if [ "$((j << i))" != "$((j << (i + width)))" ]; then + echo "Problem with $j << $i" + r=2 + fi + i=$((i + 1)) +done + +i=0 +while [ $i -lt $twowidth ]; do + if [ "$((k >> i))" != "$((k >> (i + width)))" ]; then + echo "Problem with $k >> $i" + r=2 + fi + i=$((i + 1)) +done + +exit $r