Skip to content

Fix segmentation fault triggered by negative-index value dereference#2198

Merged
CarterLi merged 1 commit intofastfetch-cli:devfrom
s0ssh:dev
Feb 24, 2026
Merged

Fix segmentation fault triggered by negative-index value dereference#2198
CarterLi merged 1 commit intofastfetch-cli:devfrom
s0ssh:dev

Conversation

@s0ssh
Copy link
Copy Markdown
Contributor

@s0ssh s0ssh commented Feb 23, 2026

…ndex

Summary

During a review, I located an off-by-one error that causes an invalid memory read (segmentation fault). Since I've determined that the address read can't be manipulated, this is only a denial-of-service, and highly unlikely to be exploited beyond this in the wild. The vector here, i.e. the way an attacker might use this bug, is by crafting a malicious configuration file and convincing users to use it - however, since the Command module exists, I don't think this bug has any impact as a security issue, thus this public PR to fix it.

All that's required to trigger this invalid memory read is passing the following config file to fastfetch:

{
  "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
  "modules": [
    {
      "type": "terminal",
      "format": "{?0}│"
    }
  ]
}

I will likely upload a more detailed breakdown of this bug to my blog (see profile) in the coming days, but I figured I should just get a fix in sooner rather than later.

UPDATE: This detailed breakdown can now be found here: https://s0s.sh/fuzzing-fastfetch-part-1/

Related issue (required for new logos for new distros)

Fixes #2193

Changes

  • Introduces checks to prevent dereferencing value at a negative index.

Checklist

  • I have tested my changes locally.

@CarterLi CarterLi merged commit fc77108 into fastfetch-cli:dev Feb 24, 2026
@CarterLi
Copy link
Copy Markdown
Member

Thanks.

I wonder how it can be a security issue, as arr[UINT32_MAX] should likely ( if not always ) be a segfault, but it doesn't read or write valid memories.

@s0ssh
Copy link
Copy Markdown
Contributor Author

s0ssh commented Feb 24, 2026

Thanks.

I wonder how it can be a security issue, as arr[UINT32_MAX] should likely ( if not always ) be a segfault, but it doesn't read or write valid memories.

If index is UINT32_MAX, it triggers the index > numArgs check, since numArgs is always 8 for the terminal module, which leads to arguments[UINT32_MAX] never being accessed.

However, an attacker would need to control what index - 1 resolved to much more than is possible here to be able to exploit the arbitrary read, which is not possible due to checks in getArgumentIndex, so it's not an exploitable security issue, just a bug.

@CarterLi
Copy link
Copy Markdown
Member

Thanks.
I wonder how it can be a security issue, as arr[UINT32_MAX] should likely ( if not always ) be a segfault, but it doesn't read or write valid memories.

If index is UINT32_MAX, it triggers the index > numArgs check, since numArgs is always 8 for the terminal module, which leads to arguments[UINT32_MAX] never being accessed.

However, an attacker would need to control what index - 1 resolved to much more than is possible here to be able to exploit the arbitrary read, which is not possible due to checks in getArgumentIndex, so it's not an exploitable security issue, just a bug.

I meant, the type of index is uint32_t, when index == 0, index - 1 is equals to UINT32_MAX.

@s0ssh
Copy link
Copy Markdown
Contributor Author

s0ssh commented Mar 5, 2026

I wonder how it can be a security issue, as arr[UINT32_MAX] should likely ( if not always ) be a segfault, but it doesn't read or write valid memories.

If index is UINT32_MAX, it triggers the index > numArgs check, since numArgs is always 8 for the terminal module, which leads to arguments[UINT32_MAX] never being accessed.
However, an attacker would need to control what index - 1 resolved to much more than is possible here to be able to exploit the arbitrary read, which is not possible due to checks in getArgumentIndex, so it's not an exploitable security issue, just a bug.

I meant, the type of index is uint32_t, when index == 0, index - 1 is equals to UINT32_MAX.

I see what's going on here. You're right that when index == 0, index - 1 = UINT32_MAX, but that bypasses the earlier check that index > numArgs (where numArgs is 8 in the context of this bug). In other words, if getArgumentIndex returns UINT32_MAX earlier, that index > numArgs check would be triggered and the dereference would not occur, but since index is 0, the check is not triggered and the dereference occurs with a value of index - 1, which is in that case UINT32_MAX. This causes the segmentation fault, which as I said earlier, I don't believe is in this case exploitable as a security issue, and is just a local denial of service bug.

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.

[BUG] Security vulnerability in fastfetch

2 participants