Skip to content

Commit c84c405

Browse files
author
Andy C
committed
[translation] Fix 32-bit truncation in (( status and for (( condition
Bugs reported by Koiche Murase on Zulip. - We are still using mops.BigTruncate() in BashArray indexing and slicing. - However that data structure may change, so I'm not touching it right now. - The printf bug still needs to be fixed. It's because we use 32-bit to_int() rather than 64-bit mops::FromStr().
1 parent cfed6c3 commit c84c405

File tree

4 files changed

+66
-7
lines changed

4 files changed

+66
-7
lines changed

builtin/printf_osh.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,9 @@ def _Format(self, parts, varargs, locs, out):
312312

313313
try:
314314
# note: spaces like ' -42 ' accepted and normalized
315+
# TODO: use mops.FromStr()
316+
# And mylib.hex_lower() etc. may have to change
317+
315318
d = int(s)
316319
except ValueError:
317320
# 'a is interpreted as the ASCII value of 'a'
@@ -352,8 +355,8 @@ def _Format(self, parts, varargs, locs, out):
352355
# state.
353356

354357
tzcell = self.mem.GetCell('TZ')
355-
if tzcell and tzcell.exported and tzcell.val.tag(
356-
) == value_e.Str:
358+
if (tzcell and tzcell.exported and
359+
tzcell.val.tag() == value_e.Str):
357360
tzval = cast(value.Str, tzcell.val)
358361
posix.putenv('TZ', tzval.s)
359362

osh/cmd_eval.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
from osh import braces
8484
from osh import sh_expr_eval
8585
from osh import word_eval
86+
from mycpp import mops
8687
from mycpp import mylib
8788
from mycpp.mylib import log, probe, switch, tagswitch
8889
from ysh import expr_eval
@@ -1251,8 +1252,8 @@ def _DoForExpr(self, node):
12511252
while True:
12521253
if for_cond:
12531254
# We only accept integers as conditions
1254-
cond_int = self.arith_ev.EvalToInt(for_cond)
1255-
if cond_int == 0: # false
1255+
cond_int = self.arith_ev.EvalToBigInt(for_cond)
1256+
if mops.Equal(cond_int, mops.ZERO): # false
12561257
break
12571258

12581259
try:
@@ -1574,8 +1575,8 @@ def _Dispatch(self, node, cmd_st):
15741575

15751576
cmd_st.check_errexit = True
15761577
cmd_st.show_code = True # this is a "leaf" for errors
1577-
i = self.arith_ev.EvalToInt(node.child)
1578-
status = 1 if i == 0 else 0
1578+
i = self.arith_ev.EvalToBigInt(node.child)
1579+
status = 1 if mops.Equal(i, mops.ZERO) else 0
15791580

15801581
elif case(command_e.ControlFlow): # LEAF command
15811582
node = cast(command.ControlFlow, UP_node)

spec/bugs.test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ printf '%u\n' 2147483648
367367
2147483648
368368
## END
369369

370-
#### bit shift bug (Koiche on Zulip)
370+
#### (( status bug
371371
case $SH in dash|ash) exit ;; esac
372372

373373
(( 1 << 32 ))

spec/for-expr.test.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,58 @@ for ((i = $"3"; i < $"5"; ++i)); do echo $i; done
116116
## OK zsh STDOUT:
117117
## END
118118

119+
120+
#### Integers near 31, 32, 62 bits
121+
122+
# Hm this was never a bug, but it's worth testing.
123+
# The bug was EvalToInt() in the condition.
124+
125+
for base in 31 32 62; do
126+
127+
start=$(( (1 << $base) - 2))
128+
end=$(( (1 << $base) + 2))
129+
130+
for ((i = start; i < end; ++i)); do
131+
echo $i
132+
done
133+
echo ---
134+
done
135+
136+
## STDOUT:
137+
2147483646
138+
2147483647
139+
2147483648
140+
2147483649
141+
---
142+
4294967294
143+
4294967295
144+
4294967296
145+
4294967297
146+
---
147+
4611686018427387902
148+
4611686018427387903
149+
4611686018427387904
150+
4611686018427387905
151+
---
152+
## END
153+
154+
155+
#### Condition that's greater than 32 bits
156+
157+
iters=0
158+
159+
for ((i = 1 << 32; i; ++i)); do
160+
echo $i
161+
iters=$(( iters + 1 ))
162+
if test $iters -eq 5; then
163+
break
164+
fi
165+
done
166+
167+
## STDOUT:
168+
4294967296
169+
4294967297
170+
4294967298
171+
4294967299
172+
4294967300
173+
## END

0 commit comments

Comments
 (0)