aws / aws/aws-cli

aws configure set: UnboundLocalError (crash) when updating an empty nested config section

Open
#10,587 1 comment 0 reactions 0 assignees View on GitHub
needs-triage
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.