Skip to content

Commit fd241a7

Browse files
authored
[core/state] Mem alloc fix: Don't initialize sparse array with a long List[str] (#2268)
* [spec/ble-sparse] Add test case for `unset[-1]=1` * and fix bug * [refactor core/bash_impl] Add "BashArray_New"
1 parent f2ac5a2 commit fd241a7

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

builtin/assign_osh.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ def _ReconcileTypes(rval, flag_a, flag_A, blame_word):
289289
# mycpp limitation: NewDict() needs to be typed
290290
tmp = NewDict() # type: Dict[str, str]
291291
return value.BashAssoc(tmp)
292-
#return bash_impl.BashArray_FromList([])
292+
#return bash_impl.BashArray_New()
293293

294294
if rval.tag() != value_e.BashAssoc:
295295
e_usage("Got -A but RHS isn't an associative array",
@@ -323,7 +323,7 @@ def Run(self, cmd_val):
323323
for pair in cmd_val.pairs:
324324
if pair.rval is None:
325325
if arg.a:
326-
rval = bash_impl.BashArray_FromList([]) # type: value_t
326+
rval = bash_impl.BashArray_New() # type: value_t
327327
elif arg.A:
328328
# mycpp limitation: NewDict() needs to be typed
329329
tmp = NewDict() # type: Dict[str, str]
@@ -459,7 +459,7 @@ def Run(self, cmd_val):
459459
if arg.a:
460460
if old_val.tag() not in (value_e.InternalStringArray,
461461
value_e.BashArray):
462-
rval = bash_impl.BashArray_FromList([])
462+
rval = bash_impl.BashArray_New()
463463
elif arg.A:
464464
if old_val.tag() != value_e.BashAssoc:
465465
# mycpp limitation: NewDict() needs to be typed

core/bash_impl.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,15 @@ def BashAssoc_ToStrForShellPrint(assoc_val):
347347
# BashArray come here.
348348

349349

350+
def BashArray_New():
351+
# type: () -> value.BashArray
352+
d = {} # type: Dict[mops.BigInt, str]
353+
max_index = mops.MINUS_ONE # max index for empty array
354+
return value.BashArray(d, max_index)
355+
356+
350357
def BashArray_FromList(strs):
351358
# type: (List[str]) -> value.BashArray
352-
353359
d = {} # type: Dict[mops.BigInt, str]
354360
max_index = mops.MINUS_ONE # max index for empty array
355361
for s in strs:

core/state.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,8 @@ def SetValue(self, lval, val, which_scopes, flags=0):
20042004
cell, var_frame, _ = self._ResolveNameOrRef(
20052005
lval.name, which_scopes)
20062006
if not cell:
2007-
self._BindNewArrayWithEntry(var_frame, lval, rval, flags)
2007+
self._BindNewArrayWithEntry(var_frame, lval, rval, flags,
2008+
left_loc)
20082009
return
20092010

20102011
if cell.readonly:
@@ -2015,7 +2016,7 @@ def SetValue(self, lval, val, which_scopes, flags=0):
20152016
with tagswitch(UP_cell_val) as case2:
20162017
if case2(value_e.Undef):
20172018
self._BindNewArrayWithEntry(var_frame, lval, rval,
2018-
flags)
2019+
flags, left_loc)
20192020
return
20202021

20212022
elif case2(value_e.Str):
@@ -2076,13 +2077,16 @@ def SetValue(self, lval, val, which_scopes, flags=0):
20762077
else:
20772078
raise AssertionError(lval.tag())
20782079

2079-
def _BindNewArrayWithEntry(self, var_frame, lval, val, flags):
2080-
# type: (Dict[str, Cell], sh_lvalue.Indexed, value.Str, int) -> None
2080+
def _BindNewArrayWithEntry(self, var_frame, lval, val, flags, blame_loc):
2081+
# type: (Dict[str, Cell], sh_lvalue.Indexed, value.Str, int, loc_t) -> None
20812082
"""Fill 'var_frame' with a new indexed array entry."""
2082-
no_str = None # type: Optional[str]
2083-
items = [no_str] * lval.index
2084-
items.append(val.s)
2085-
new_value = bash_impl.BashArray_FromList(items)
2083+
2084+
new_value = bash_impl.BashArray_New()
2085+
error_code = bash_impl.BashArray_SetElement(new_value,
2086+
mops.IntWiden(lval.index),
2087+
val.s)
2088+
if error_code == error_code_e.IndexOutOfRange:
2089+
e_die("Index %d is out of bounds for array of length 0", blame_loc)
20862090

20872091
# arrays can't be exported; can't have BashAssoc flag
20882092
readonly = bool(flags & SetReadOnly)

spec/ble-sparse.test.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,3 +1181,23 @@ json write (crash_dump.var_stack[0].a)
11811181

11821182
## N-I bash/mksh STDOUT:
11831183
## END
1184+
1185+
1186+
#### Regression: a[-1]=1
1187+
case $SH in mksh) exit ;; esac
1188+
1189+
a[-1]=1
1190+
1191+
## status: 1
1192+
## STDOUT:
1193+
## END
1194+
## STDERR:
1195+
a[-1]=1
1196+
^~
1197+
[ stdin ]:3: fatal: Index %d is out of bounds for array of length 0
1198+
## END
1199+
## OK bash STDERR:
1200+
bash: line 3: a[-1]: bad array subscript
1201+
## END
1202+
## N-I mksh status: 0
1203+
## N-I mksh stderr-json: ""

0 commit comments

Comments
 (0)