aws configure set: UnboundLocalError (crash) when updating an empty nested config section
- Dominant language
- Python
- Stars
- 17.3k
- Forks
- 4.6k
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 13
Description
## Describe the bug
`ConfigFileWriter._update_subattributes` (`awscli/customizations/configure/writer.py`) is responsible for writing values into a nested config section, e.g.:
```
[default]
s3 =
signature_version = s3v4
```
```python
def _update_subattributes(self, index, contents, values, starting_indent):
index += 1
for i in range(index, len(contents)):
line = contents[i]
match = self.OPTION_REGEX.search(line)
if match is not None:
current_indent = len(
match.group(1)) - len(match.group(1).lstrip())
key_name = match.group(1).strip()
if key_name in values:
...
if starting_indent == current_indent or \
self.SECTION_REGEX.search(line) is not None:
...
```
`current_indent` is only assigned inside `if match is not None:`. If the nested section is currently **empty** (e.g. `s3 =` with no sub-keys yet under it — a completely valid, documented config state, e.g. right after `s3 =` is first created, or hand-edited), then on the very first loop iteration:
- If the next line is another `[section]` header (no `OPTION_REGEX` match), `current_indent` was never assigned, and the reference at `if starting_indent == current_indent` raises `UnboundLocalError`.
- If the empty `s3 =` stanza is the last line in the file, the `for` loop range is empty, so `current_indent` (and `i`) are never assigned, and the `else` clause of the `for/else` raises the same error.
## Repro
```python
import tempfile, os
from awscli.customizations.configure.writer import ConfigFileWriter
content = "[default]\ns3 =\n[profile foo]\nfoo = bar\n"
fd, path = tempfile.mkstemp()
open(path, 'w').write(content)
w = ConfigFileWriter()
w.update_config({'__section__': 'default', 's3': {'addressing_style': 'path'}}, path)
```
Output:
```
Traceback (most recent call last):
...
File "awscli/customizations/configure/writer.py", line 231, in _update_subattributes
if starting_indent == current_indent or \
^^^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'current_indent' where it is not associated with a value
```
Same crash (different line) when `s3 =` is the last line of the file with nothing after it.
## Real-world trigger
Running `aws configure set s3. ` (or `s3api.`, or any nested `.` set) against a config file where the target nested section exists but has no sub-keys under it yet throws an unhandled `UnboundLocalError` instead of writing the value.
## Suggested fix
Initialize `current_indent = None` (and `i = index - 1`) before the loop, so a line/range with no `OPTION_REGEX` match doesn't leave the variables unbound, while preserving the existing control flow (`None` never equals `starting_indent`, so behavior for all previously-passing cases is unchanged).
I have a PR ready with this fix plus two new regression tests covering both empty-stanza cases (followed by another section, and at end-of-file). Both new tests reproduce the `UnboundLocalError` against the current code and pass with the fix; full `tests/unit/customizations/configure/` (109) and `tests/functional/configure/` (33) suites pass with no regressions.
## Environment
- `aws-cli` develop branch (current)
Contributor guide
Research direction
Start in awscli/customizations/configure/writer.py at ConfigFileWriter._update_subattributes and reproduce the two empty-stanza cases described in the issue. Run tests/unit/customizations/configure/ and tests/functional/configure/; done means both cases write the nested value without UnboundLocalError and the existing suites remain passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100