GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix str.expandtabs aborting on a tab size of zero by luantaraschi · Pull Request #8562 · RustPython/RustPython

Conversation

@luantaraschi

@luantaraschi luantaraschi commented Aug 20, 2026 •
edited by coderabbitai Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

"a\tb".expandtabs(0) takes the interpreter down:

$ rustpython -c 'print("a\tb".expandtabs(0))'
thread 'main' panicked at library/alloc/src/raw_vec/mod.rs:28:5:
capacity overflow

CPython returns 'ab': with no width to advance to, the tabs come out and nothing else moves. expandtabs(-1) is the same, because ExpandTabsArgs::tabsize sends every negative value to 0.

rustpython_common::str::expandtabs walks the string with the tab stop in tab_size and the current column in col_count, and on a tab it does tab_size - col_count. Both start at zero, so the first character makes col_count 1 while tab_size stays 0, and the subtraction underflows. The run of spaces asked for next is usize::MAX, and the allocation aborts the process. That is why a tab has to follow something: "\ta".expandtabs(0) starts the tab at column 0, subtracts 0 from 0, and comes out right by accident.

BytesInner::expandtabs already returns early for this, filtering the tabs out. The string version now does the same thing.

Reachable from any Python code, no C API and no unusual build needed:

"\t".join(parts).expandtabs(user_supplied_width)

Checked against CPython 3.14.7 over 23 subjects by 10 tab sizes by str, bytes and bytearray, 460 cases. All 460 agree now. Without the change 42 of them abort the process, and the bytes half is not among them, which is where the shape of the fix came from.

Tests are in crates/common/src/str.rs next to the function and in extra_tests/snippets/builtin_str.py alongside the expandtabs overflow cases that landed in #8524. Both cover the zero and negative sizes, ASCII and non-ASCII, tabs after a newline and after a carriage return, and a set of ordinary tab sizes so a fix that reached too far would show up.

Lib/test/string_tests.py has no case for a zero tab size, so test_str and test_bytes pass either way. They still pass here, along with test_textwrap, 523 tests.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed expandtabs handling for zero tab sizes, preventing excessive memory allocation and process termination.
    • Zero tab sizes now remove tab characters consistently across strings, bytes, and bytearrays.
    • Preserved existing behavior for positive tab sizes, including multiline and multibyte text.
  • Tests

    • Added coverage for zero, negative, and positive tab sizes across varied input types and content.
    • Added coverage for Unicode-safe replacement using empty patterns.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@coderabbitai

coderabbitai Bot commented Aug 20, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: facf520a-6186-4010-82c9-56e8a01639e1

📥 Commits

Reviewing files that changed from the base of the PR and between a707729 and 410844f.

📒 Files selected for processing (1)
  • extra_tests/snippets/builtin_str.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

expandtabs now removes tabs for a zero tab size instead of allocating an oversized space run. Rust and Python tests cover zero, negative, and positive tab sizes. Python tests also cover empty-pattern replacement.

Changes

Expandtabs zero-tab-size handling

Layer / File(s) Summary
Zero tab-size behavior
crates/common/src/str.rs, extra_tests/snippets/builtin_str.py
expandtabs removes tab characters when tab_size is zero. Rust and Python tests cover zero, negative, and positive tab sizes across strings, bytes, bytearrays, Unicode content, and line boundaries.

Empty-pattern replacement coverage

Layer / File(s) Summary
Empty-pattern replacement regression coverage
extra_tests/snippets/builtin_str.py
Python tests cover empty-pattern replacement for ASCII, Unicode, empty inputs, insertion counts, and ordinary replacement behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 41084

This change prevents process termination for zero or negative tab sizes and adds focused coverage; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: youknowone

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: preventing str.expandtabs from aborting when the tab size is zero.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
  • X
  • Mastodon
  • Reddit
  • LinkedIn

Comment @coderabbitai help to get the list of available commands.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@luantaraschi luantaraschi mentioned this pull request Aug 21, 2026
Drop the lint expectations clippy 1.98 no longer fulfils #8564
Merged
1 task done
@luantaraschi
Fix str.expandtabs aborting on a tab size of zero
410844f
`"a\tb".expandtabs(0)` panicked with a capacity overflow. CPython returns
`'ab'`: with no width to advance to, the tabs come out and nothing else
moves. `expandtabs(-1)` is the same call, since `ExpandTabsArgs::tabsize`
sends every negative value to 0.

`expandtabs` keeps the tab stop in `tab_size` and the current column in
`col_count`, and on a tab it does `tab_size - col_count`. With a tab size of
zero both start at 0, the first character makes `col_count` 1 while
`tab_size` stays 0, and the subtraction underflows. The run of spaces asked
for next is `usize::MAX`, and the allocation aborts the process. A tab has to
follow something on the line to reach it: `"\ta".expandtabs(0)` subtracts 0
from 0 and comes out right by accident.

`BytesInner::expandtabs` already returns early for this and filters the tabs
out. The string version now does the same.

Assisted-by: Claude Code:claude-opus-5
@luantaraschi
luantaraschi force-pushed the fix/expandtabs-zero-tabsize branch from a707729 to 410844f Compare August 21, 2026 07:47
youknowone
youknowone approved these changes Aug 21, 2026
View reviewed changes

@youknowone youknowone left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

👍

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@youknowone
youknowone merged commit 6f542bf into RustPython:main Aug 21, 2026
25 of 27 checks passed

Uh oh!

There was an error while loading. Please reload this page.

youknowone pushed a commit that referenced this pull request Sep 16, 2026
@luantaraschi
Fix str.expandtabs aborting on a tab size of zero (#8562)
cdb8a8d
`"a\tb".expandtabs(0)` panicked with a capacity overflow. CPython returns
`'ab'`: with no width to advance to, the tabs come out and nothing else
moves. `expandtabs(-1)` is the same call, since `ExpandTabsArgs::tabsize`
sends every negative value to 0.

`expandtabs` keeps the tab stop in `tab_size` and the current column in
`col_count`, and on a tab it does `tab_size - col_count`. With a tab size of
zero both start at 0, the first character makes `col_count` 1 while
`tab_size` stays 0, and the subtraction underflows. The run of spaces asked
for next is `usize::MAX`, and the allocation aborts the process. A tab has to
follow something on the line to reach it: `"\ta".expandtabs(0)` subtracts 0
from 0 and comes out right by accident.

`BytesInner::expandtabs` already returns early for this and filters the tabs
out. The string version now does the same.

Assisted-by: Claude Code:claude-opus-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@youknowone youknowone youknowone approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@luantaraschi @youknowone
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.