diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-10-28 13:17:29 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-10-28 13:17:29 -0200 |
commit | f39034889d010f6f81257dde9517a9ad4d021d1c (patch) | |
tree | 766b5429e95c6ae6a0753ce7c3f67c66095c6bfa | |
parent | 6b053a63cb10395d310a043b91bd421656446e78 (diff) | |
download | lua-f39034889d010f6f81257dde9517a9ad4d021d1c.tar.gz lua-f39034889d010f6f81257dde9517a9ad4d021d1c.tar.bz2 lua-f39034889d010f6f81257dde9517a9ad4d021d1c.zip |
stricter control over number of bits in each operation
-rw-r--r-- | lbitlib.c | 32 |
1 files changed, 20 insertions, 12 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbitlib.c,v 1.8 2010/10/25 20:31:11 roberto Exp roberto $ | 2 | ** $Id: lbitlib.c,v 1.9 2010/10/27 16:50:32 roberto Exp roberto $ |
3 | ** Standard library for bitwise operations | 3 | ** Standard library for bitwise operations |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,12 +13,16 @@ | |||
13 | #include "lualib.h" | 13 | #include "lualib.h" |
14 | 14 | ||
15 | 15 | ||
16 | /* number of bits considered when shifting/rotating (must be a power of 2) */ | 16 | /* number of bits to consider in a number */ |
17 | #define NBITS 32 | 17 | #define NBITS 32 |
18 | 18 | ||
19 | #define ALLONES (~(((~(lua_Unsigned)0) << (NBITS - 1)) << 1)) | ||
19 | 20 | ||
20 | typedef LUA_INT32 b_int; | 21 | /* mask to trim extra bits */ |
21 | typedef unsigned LUA_INT32 b_uint; | 22 | #define trim(x) ((x) & ALLONES) |
23 | |||
24 | |||
25 | typedef lua_Unsigned b_uint; | ||
22 | 26 | ||
23 | 27 | ||
24 | #define getuintarg(L,arg) luaL_checkunsigned(L,arg) | 28 | #define getuintarg(L,arg) luaL_checkunsigned(L,arg) |
@@ -29,7 +33,7 @@ static b_uint andaux (lua_State *L) { | |||
29 | b_uint r = ~(b_uint)0; | 33 | b_uint r = ~(b_uint)0; |
30 | for (i = 1; i <= n; i++) | 34 | for (i = 1; i <= n; i++) |
31 | r &= getuintarg(L, i); | 35 | r &= getuintarg(L, i); |
32 | return r; | 36 | return trim(r); |
33 | } | 37 | } |
34 | 38 | ||
35 | 39 | ||
@@ -52,7 +56,7 @@ static int b_or (lua_State *L) { | |||
52 | b_uint r = 0; | 56 | b_uint r = 0; |
53 | for (i = 1; i <= n; i++) | 57 | for (i = 1; i <= n; i++) |
54 | r |= getuintarg(L, i); | 58 | r |= getuintarg(L, i); |
55 | lua_pushunsigned(L, r); | 59 | lua_pushunsigned(L, trim(r)); |
56 | return 1; | 60 | return 1; |
57 | } | 61 | } |
58 | 62 | ||
@@ -62,14 +66,14 @@ static int b_xor (lua_State *L) { | |||
62 | b_uint r = 0; | 66 | b_uint r = 0; |
63 | for (i = 1; i <= n; i++) | 67 | for (i = 1; i <= n; i++) |
64 | r ^= getuintarg(L, i); | 68 | r ^= getuintarg(L, i); |
65 | lua_pushunsigned(L, r); | 69 | lua_pushunsigned(L, trim(r)); |
66 | return 1; | 70 | return 1; |
67 | } | 71 | } |
68 | 72 | ||
69 | 73 | ||
70 | static int b_not (lua_State *L) { | 74 | static int b_not (lua_State *L) { |
71 | b_uint r = ~getuintarg(L, 1); | 75 | b_uint r = ~getuintarg(L, 1); |
72 | lua_pushunsigned(L, r); | 76 | lua_pushunsigned(L, trim(r)); |
73 | return 1; | 77 | return 1; |
74 | } | 78 | } |
75 | 79 | ||
@@ -77,12 +81,14 @@ static int b_not (lua_State *L) { | |||
77 | static int b_shift (lua_State *L, b_uint r, int i) { | 81 | static int b_shift (lua_State *L, b_uint r, int i) { |
78 | if (i < 0) { /* shift right? */ | 82 | if (i < 0) { /* shift right? */ |
79 | i = -i; | 83 | i = -i; |
84 | r = trim(r); | ||
80 | if (i >= NBITS) r = 0; | 85 | if (i >= NBITS) r = 0; |
81 | else r >>= i; | 86 | else r >>= i; |
82 | } | 87 | } |
83 | else { /* shift left */ | 88 | else { /* shift left */ |
84 | if (i >= NBITS) r = 0; | 89 | if (i >= NBITS) r = 0; |
85 | else r <<= i; | 90 | else r <<= i; |
91 | r = trim(r); | ||
86 | } | 92 | } |
87 | lua_pushunsigned(L, r); | 93 | lua_pushunsigned(L, r); |
88 | return 1; | 94 | return 1; |
@@ -102,12 +108,12 @@ static int b_rshift (lua_State *L) { | |||
102 | static int b_arshift (lua_State *L) { | 108 | static int b_arshift (lua_State *L) { |
103 | b_uint r = getuintarg(L, 1); | 109 | b_uint r = getuintarg(L, 1); |
104 | int i = luaL_checkint(L, 2); | 110 | int i = luaL_checkint(L, 2); |
105 | if (i < 0 || !(r & 0x80000000)) | 111 | if (i < 0 || !(r & (1 << (NBITS - 1)))) |
106 | return b_shift(L, r, -i); | 112 | return b_shift(L, r, -i); |
107 | else { /* arithmetic shift for 'negative' number */ | 113 | else { /* arithmetic shift for 'negative' number */ |
108 | if (i >= NBITS) r = 0xffffffff; | 114 | if (i >= NBITS) r = ALLONES; |
109 | else | 115 | else |
110 | r = (r >> i) | ~(~(b_uint)0 >> i); /* add signal bit */ | 116 | r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ |
111 | lua_pushunsigned(L, r); | 117 | lua_pushunsigned(L, r); |
112 | return 1; | 118 | return 1; |
113 | } | 119 | } |
@@ -117,8 +123,9 @@ static int b_arshift (lua_State *L) { | |||
117 | static int b_rot (lua_State *L, int i) { | 123 | static int b_rot (lua_State *L, int i) { |
118 | b_uint r = getuintarg(L, 1); | 124 | b_uint r = getuintarg(L, 1); |
119 | i &= (NBITS - 1); /* i = i % NBITS */ | 125 | i &= (NBITS - 1); /* i = i % NBITS */ |
126 | r = trim(r); | ||
120 | r = (r << i) | (r >> (NBITS - i)); | 127 | r = (r << i) | (r >> (NBITS - i)); |
121 | lua_pushunsigned(L, r); | 128 | lua_pushunsigned(L, trim(r)); |
122 | return 1; | 129 | return 1; |
123 | } | 130 | } |
124 | 131 | ||
@@ -153,3 +160,4 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) { | |||
153 | luaL_newlib(L, bitlib); | 160 | luaL_newlib(L, bitlib); |
154 | return 1; | 161 | return 1; |
155 | } | 162 | } |
163 | |||