Skip to content

Fix cpumeter segfault#2025

Open
fasterit wants to merge 2 commits into
htop-dev:mainfrom
fasterit:fix-cpumeter-segfault
Open

Fix cpumeter segfault#2025
fasterit wants to merge 2 commits into
htop-dev:mainfrom
fasterit:fix-cpumeter-segfault

Conversation

@fasterit

Copy link
Copy Markdown
Member

Fixes: #2024
and some int -> unsigned int mopping up old code (2nd commit)

Daniel Lange added 2 commits June 17, 2026 04:29
…rs array on CPU count change

When CPUs are hot-added while htop is running, LinuxMachine_scanCPUInfo
updates existingCPUs. The next Header_updateData call invokes
AllCPUsMeter_updateValues, which queries the new (larger) count from
AllCPUsMeter_getRange but accesses data->meters that was sized for the
old count hence causing an out-of-bounds access and SIGSEGV.

Changes:
- Rewriting CPUMeterCommonInit to detect count changes and resize
  data->meters (freeing excess meters when shrinking, reallocating and
  zero-filling when growing). data->cpus now stores the actual allocated
  meter count rather than existingCPUs.
- Having AllCPUsMeter_updateValues detect a count mismatch and call
  CPUMeterCommonInit before iterating over the meters array.
- Updating AllCPUsMeter_done to iterate over data->cpus (the number of
  meters actually allocated) instead of re-deriving via
  AllCPUsMeter_getRange, avoiding the same class of bug at teardown.
- Having CPUMeterCommonUpdateMode call CPUMeterCommonInit upfront for
  the same reason.

Fixes: htop-dev#2024

Assisted-by: Microsoft Copilot/Claude Sonnet 4.6
Assisted-by: Microsoft Copilot/Claude Sonnet 4.6
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

AllCPUsMeter_getRange output parameters change from int* to unsigned int*. CPUMeterCommonInit is rewritten to reallocate the per-CPU Meter* array when the requested CPU count differs from the previously allocated data->cpus, zero-filling new slots and updating data->cpus to reflect the new allocation. AllCPUsMeter_updateValues detects CPU count changes at update time and re-invokes CPUMeterCommonInit before iterating meters. AllCPUsMeter_done simplifies cleanup by iterating directly to data->cpus. CPUMeterCommonDraw and SingleColCPUsMeter_draw convert range and loop variables to unsigned types.

Assessment against linked issues

Objective Addressed Explanation
Fix segfault when vCPUs are added live (hot-plug) while htop is running [#2024]

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes identified.

Poem

The CPUs grew while htop stood watch,
An unsigned count kept the index on notch.
Realloc'd the array, zero-filled the gap,
No stale pointer left to trigger the trap.
Hot-plugged and stable — no SIGSEGV map.


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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 87ab446d-e4db-4308-9c1a-aa046c8dde8d

📥 Commits

Reviewing files that changed from the base of the PR and between e9518b3 and 6f86c5f.

📒 Files selected for processing (1)
  • CPUMeter.c

Comment thread CPUMeter.c
@BenBE BenBE added bug 🐛 Something isn't working code quality ♻️ Code quality enhancement labels Jun 17, 2026
@BenBE BenBE added this to the 3.6.0 milestone Jun 17, 2026
Comment thread CPUMeter.c Outdated
data->meters = xReallocArray(data->meters, (unsigned int)count, sizeof(Meter*));
/* zero-fill newly added entries */
if ((unsigned int)count > prevCount)
memset(data->meters + prevCount, 0, ((unsigned int)count - prevCount) * sizeof(Meter*));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider using xReallocArrayZero.

Comment thread CPUMeter.c
assert(count >= 0);
unsigned int prevCount = data->cpus;
if ((unsigned int)count != prevCount) {
prevCount = data->cpus;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The declaration of prevCount should be moved back here. There's no use of prevCount before this line.

Comment thread CPUMeter.c
int xpos = x + ((i / nrows) * colwidth) + d;
unsigned int nrows = (count + ncol - 1) / ncol;
for (unsigned int i = 0; i < count; i++) {
int col = i / nrows;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There's an implicit cast from unsigned int to int here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug 🐛 Something isn't working code quality ♻️ Code quality enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segmentation fault in 3.4.1 after adding virtual CPUs

3 participants