Skip to content

Make settings.toml numbers follow TOML and use less flash - #11620

Merged
dhalbert merged 7 commits into
adafruit:mainfrom
mikeysklar:settings-toml-leading-zero
Oct 18, 2026
Merged

dhalbert merged 7 commits into
adafruit:mainfrom
mikeysklar:settings-toml-leading-zero

Conversation

@mikeysklar

@mikeysklar mikeysklar commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

What

supervisor.get_setting() now rejects numbers with leading zeros and reads integers with a small built-in parser.

Why

017 was read as octal 15, which TOML does not allow.

Dropping strtol() also saves flash.

settings.toml before after
017, -017, 00 15, -15, 0 ValueError
08, 01.5, 007e1 8.0, 1.5, 70.0 ValueError
0o17, 0b101 ValueError 15, 5
1_000 1000.0 1000
0xFFFFFFFF 2147483647 ValueError
99999999999 2147483647 100000000000.0
"\u+041" 'A' ValueError
0, -17, +17, 0x11, 0X1f, 0.5, 1e3 unchanged unchanged

Bad startup settings print "Invalid format" and keep their default.

An oversized CIRCUITPY_WEB_API_PORT now uses port 80 instead of 65535.

The integer parser is from @dhalbert.

Flash vs. this PR before the parser bytes
Feather nRF52840 -804
Metro RP2040 -764
Metro RP2350 -440
Metro ESP32-S3 (.bin) +32, web workflow still links strtoul()
Testing (Ubuntu host) Result
tests/circuitpython-manual/settings on Metro RP2040, Feather nRF52840, Metro ESP32-S3 34/34 PASS on each
58 extra edge cases on the same boards as in the table above
unix coverage make test 982 passed

Out of scope: 0_17 and 1_ are accepted, \uD800 surrogates are accepted, binary values longer than 13 digits do not fit the buffer.

Written with Claude Code, which also ran the tests above. I reviewed the code and this description.

🤖 Generated with Claude Code

TOML does not allow leading zeros on decimal integers or on the integer
part of floats (https://toml.io/en/v1.0.0#integer). strtol base 0 read
017 as octal 15, and values like 08 or 01.5 fell through to the float
parser. They now return SETTINGS_ERR_BAD_VALUE like other invalid numbers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@dhalbert dhalbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - couple of minor points.

Comment thread supervisor/shared/settings.c Outdated
Comment thread tests/circuitpython-manual/settings/settings.toml
mikeysklar and others added 2 commits October 16, 2026 09:18
TOML allows leading zeros after the 0x prefix, so check that 0x000F
still parses as 15. Note in environment.rst that TOML allows 0o, 0b
and underscores, and only this parser does not.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TOML allows underscores between digits in integers and floats, such as
1_000 or 0x1234_abcd. Each underscore must have a digit on both sides.

Before, strtol() stopped at the underscore, so 1_000 fell through to the
float parser and came back as 1000.0. mp_parse_float_internal() skips
any underscore, so 1__0, _1 and 1_ were also accepted.

Remove underscores in place after checking each one, before parsing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeysklar
mikeysklar requested a review from dhalbert October 16, 2026 21:18

@dhalbert dhalbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What provoked this PR in the first place? Was there some case where someone had leading zeros and it was interpreted as octal?

Comment thread supervisor/shared/settings.c Outdated
Comment thread supervisor/shared/settings.c Outdated
@mikeysklar

Copy link
Copy Markdown
Collaborator Author

This was part of the test fixture design for CircuitPython. A hardware test that checks settings.toml against values TOML rejects found that 017 was read as octal 15 on every board.

It seemed worth fixing before anyone hit it.

mikeysklar and others added 2 commits October 16, 2026 14:59
This reverts commit 50ee27e. The extra code is not worth it: we do
not need to match the TOML underscore rules exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Only a digit after the leading 0 needs to be rejected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeysklar
mikeysklar requested a review from dhalbert October 16, 2026 22:27
Replace strtol() in get_int() and strtoul() in read_unicode_escape()
with a small digit parser. This drops strtol, strtoul, _ctype_, errno
and _impure_data from the link: -660 bytes flash and -80 bytes RAM on
the ItsyBitsy nRF52840, -620 bytes flash on the Feather RP2040.

Integers now also accept 0o and 0b prefixes and underscores (1_000).
As a superset of TOML, a sign is allowed before 0x/0o/0b, the prefix
may be uppercase, and underscores are not checked to be between digits.

Out-of-range integers are no longer clamped to LONG_MAX.
settings_get_int() returns an error for them; supervisor.get_setting()
raises ValueError for hex, octal and binary, and returns a float for
decimal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
'@' and '`' were read as the digit 9, so 12@ parsed as 129.
Stop at any byte below 'a' after case folding.

Underscores were skipped inside \u escapes, so "\u0_41" decoded to "A".
Read escape digits directly instead of through parse_digits().
This also drops a variable-length array.

Fold the decimal leading-zero check into the existing prefix check
and move has_leading_zero() under MICROPY_PY_BUILTINS_FLOAT, since
only get_float() uses it now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@dhalbert dhalbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, smaller size and better checking.

@mikeysklar mikeysklar changed the title Reject settings.toml numbers with leading zeros, as TOML requires Make settings.toml numbers follow TOML and use less flash Oct 18, 2026
@dhalbert
dhalbert merged commit cced44d into adafruit:main Oct 18, 2026
610 of 611 checks passed
@mikeysklar
mikeysklar deleted the settings-toml-leading-zero branch October 19, 2026 00:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants