Skip to content

libs/libc: support explicit bases up to 36 - #19594

Merged
xiaoxiang781216 merged 1 commit into
apache:masterfrom
Zepp-Hanzj:fix/libc-strto-base36
Aug 1, 2026
Merged

libs/libc: support explicit bases up to 36#19594
xiaoxiang781216 merged 1 commit into
apache:masterfrom
Zepp-Hanzj:fix/libc-strto-base36

Conversation

@Zepp-Hanzj

@Zepp-Hanzj Zepp-Hanzj commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

The integer conversion interfaces document explicit bases from 2 through 36. The shared lib_checkbase() helper currently rejects bases above 26 even though lib_isbasedigit() already supports digits 0-9 and letters a-z/A-Z.

Raise the explicit-base limit from 26 to 36 so strtol(), strtoul(), strtoll(), strtoull(), strtoimax(), and strtoumax() accept the full documented range. Bases below 2 and above 36 remain invalid.

Impact

Explicit bases 27 through 36 no longer fail with EINVAL. Existing base-0 detection, bases 2 through 26, and invalid-base handling are unchanged.

Testing

Automated regression coverage

apache/nuttx-apps#3688 adds dedicated ostest coverage for bases 2 through
36, all six strto* interfaces, end pointers, errno, and invalid bases 1
and 37. The test asserts at base 27 without this fix and passes with it.

NuttX sim

Built the current upstream sim:nsh configuration and ran a dedicated 117-assertion test program covering:

  • every explicit base from 2 through 36
  • lowercase and uppercase alphabetic digits
  • all six integer conversion interfaces
  • whitespace, signs, and end pointers
  • base-36 64-bit limits and overflow saturation
  • invalid bases 1, 37, and -2
  • base-0 decimal, octal, and hexadecimal detection
  • out-of-base digits, no-conversion input, and unsigned negation
BASE36-TEST BEGIN
BASE36-TEST SUMMARY total=117 passed=117 failed=0
BASE36-TEST PASS

STM32F407ZG hardware A/B

Built and flashed the same 110-assertion test program before and after this one-line change. J-Link verified both images after programming. The serial results below are from the physical STM32F407ZG target at 115200 baud.

Before fix: 69 passed, 41 failed
BASE36-TEST BEGIN
FAIL api=strtoul case=max-lower input='q#' base=27 value=0 expected=26 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='Q#' base=27 value=0 expected=26 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=27 value=0 expected=27 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='r#' base=28 value=0 expected=27 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='R#' base=28 value=0 expected=27 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=28 value=0 expected=28 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='s#' base=29 value=0 expected=28 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='S#' base=29 value=0 expected=28 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=29 value=0 expected=29 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='t#' base=30 value=0 expected=29 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='T#' base=30 value=0 expected=29 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=30 value=0 expected=30 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='u#' base=31 value=0 expected=30 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='U#' base=31 value=0 expected=30 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=31 value=0 expected=31 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='v#' base=32 value=0 expected=31 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='V#' base=32 value=0 expected=31 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=32 value=0 expected=32 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='w#' base=33 value=0 expected=32 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='W#' base=33 value=0 expected=32 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=33 value=0 expected=33 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='x#' base=34 value=0 expected=33 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='X#' base=34 value=0 expected=33 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=34 value=0 expected=34 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='y#' base=35 value=0 expected=34 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='Y#' base=35 value=0 expected=34 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=35 value=0 expected=35 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=max-lower input='z#' base=36 value=0 expected=35 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=max-upper input='Z#' base=36 value=0 expected=35 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoul case=positional-10 input='10!' base=36 value=0 expected=36 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoul case=whitespace-plus input='   +z!' base=36 value=0 expected=35 end=0 expected_end=4 errno=22 expected_errno=0
FAIL api=strtoll case=negative input='-z!' base=36 value=0 expected=18446744073709551581 end=0 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoull case=ull-simple input='Z!' base=36 value=0 expected=35 end=0 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoimax case=imax-simple input='-z!' base=36 value=0 expected=18446744073709551581 end=1 expected_end=2 errno=22 expected_errno=0
FAIL api=strtoumax case=umax-simple input='z!' base=36 value=0 expected=35 end=-134373988 expected_end=1 errno=22 expected_errno=0
FAIL api=strtoull case=ull-max input='3w5e11264sgsf!' base=36 value=0 expected=18446744073709551615 end=0 expected_end=13 errno=22 expected_errno=0
FAIL api=strtoull case=ull-overflow input='3w5e11264sgsg!' base=36 value=0 expected=18446744073709551615 end=0 expected_end=13 errno=22 expected_errno=34
FAIL api=strtoll case=ll-max input='1y2p0ij32e8e7!' base=36 value=0 expected=9223372036854775807 end=0 expected_end=13 errno=22 expected_errno=0
FAIL api=strtoll case=ll-positive-overflow input='1y2p0ij32e8e8!' base=36 value=0 expected=9223372036854775807 end=0 expected_end=13 errno=22 expected_errno=34
FAIL api=strtoll case=ll-min input='-1y2p0ij32e8e8!' base=36 value=0 expected=9223372036854775808 end=0 expected_end=14 errno=22 expected_errno=0
FAIL api=strtoll case=ll-negative-overflow input='-1y2p0ij32e8e9!' base=36 value=0 expected=9223372036854775808 end=0 expected_end=14 errno=22 expected_errno=34
BASE36-TEST SUMMARY total=110 passed=69 failed=41
BASE36-TEST FAIL
After fix: 110 passed, 0 failed
BASE36-TEST BEGIN
BASE36-TEST SUMMARY total=110 passed=110 failed=0
BASE36-TEST PASS

Style

$ tools/checkpatch.sh -f libs/libc/stdlib/lib_checkbase.c
✔️ All checks pass.

@github-actions github-actions Bot added Area: OS Components OS Components issues Size: XS The size of the change in this PR is very small labels Aug 1, 2026
The strto* interfaces document explicit bases in the range 2 through 36, and lib_isbasedigit() already supports alphabetic digits through base 36.  However, lib_checkbase() rejects every explicit base above 26 with EINVAL.

Raise the validation limit to 36 so the conversion interfaces accept the full documented range while continuing to reject base 37 and above.

Signed-off-by: hanzhijian <hanzhijian@zepp.com>
@Zepp-Hanzj
Zepp-Hanzj force-pushed the fix/libc-strto-base36 branch from a5b143f to 9ea7bc4 Compare August 1, 2026 06:38
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

hifive1-revb

@acassis

acassis commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@Zepp-Hanzj suggestion: add some test to it on ostest

@Zepp-Hanzj

Copy link
Copy Markdown
Contributor Author

Thanks for the suggestion. I added dedicated ostest regression coverage in apache/nuttx-apps#3688. It checks every explicit base from 2 through 36, lower- and upper-case digits, all six strto* interfaces, end pointers, errno, and invalid bases 1 and 37. I verified that it asserts at the first base-27 case without this fix and passes the libc test section with this fix.

@Zepp-Hanzj
Zepp-Hanzj marked this pull request as ready for review August 1, 2026 09:58
@Zepp-Hanzj
Zepp-Hanzj requested a review from jerpelea as a code owner August 1, 2026 09:58
@xiaoxiang781216
xiaoxiang781216 merged commit ddf350f into apache:master Aug 1, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: OS Components OS Components issues Size: XS The size of the change in this PR is very small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants