diff options
author | jilles <jilles@FreeBSD.org> | 2014-08-15 22:36:41 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2014-08-15 22:36:41 +0000 |
commit | 948728c4a63d15bb4bc6fc777177b823be4ade7d (patch) | |
tree | bcbd242911551a39177c9ddee6a87c42fcc0aad9 /bin/sh/tests/expansion | |
parent | 82e14020fd65682e9c4e04af88589597b3609efa (diff) | |
download | FreeBSD-src-948728c4a63d15bb4bc6fc777177b823be4ade7d.zip FreeBSD-src-948728c4a63d15bb4bc6fc777177b823be4ade7d.tar.gz |
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.
Diffstat (limited to 'bin/sh/tests/expansion')
-rw-r--r-- | bin/sh/tests/expansion/Makefile | 1 | ||||
-rw-r--r-- | bin/sh/tests/expansion/arith14.0 | 40 |
2 files changed, 41 insertions, 0 deletions
diff --git a/bin/sh/tests/expansion/Makefile b/bin/sh/tests/expansion/Makefile index 8ded7e1..36b5fa5 100644 --- a/bin/sh/tests/expansion/Makefile +++ b/bin/sh/tests/expansion/Makefile @@ -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 diff --git a/bin/sh/tests/expansion/arith14.0 b/bin/sh/tests/expansion/arith14.0 new file mode 100644 index 0000000..8369043 --- /dev/null +++ b/bin/sh/tests/expansion/arith14.0 @@ -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 |