Skip to content

NULL pointer dereference fixes#687

Closed
PrivacyIsARight wants to merge 4 commits intovoid-linux:masterfrom
PrivacyIsARight:xbps-fixes
Closed

NULL pointer dereference fixes#687
PrivacyIsARight wants to merge 4 commits intovoid-linux:masterfrom
PrivacyIsARight:xbps-fixes

Conversation

@PrivacyIsARight
Copy link
Copy Markdown
Contributor

  1. Fixed off-by-one errors in calloc and malloc calls by adding the required byte for the null terminator.

  2. Added string length guards before strncmp operations to prevent potential buffer over-reads on short paths.

  3. Hardened pointer arithmetic by ensuring strchr results are not NULL before incrementing them.

  4. Replaced assert() with conditional checks to allow the tool to skip malformed entries gracefully instead of crashing.

  5. Improved hashing safety by using sizeof on the destination buffer (xe->sha256) rather than local variables.

  6. Ensured memory integrity by calling free() on local allocations before skipping iterations in the new error paths.

You can test the PoC out with a command like this.

ASAN_OPTIONS=detect_leaks=0 ./bin/xbps-create/xbps-create \
    -A noarch -n "malicious-pkg-1.0_1" \
    -s "PoC for NULL dereference" \
    --alternatives "MALFORMED_ENTRY_NO_COLON" \
    mock_pkg 2>&1 | tee xbps_asan_output.txt

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

With the changes applied it now returns:

ASAN_OPTIONS=detect_leaks=0 ./bin/xbps-create/xbps-create
-A noarch -n "malicious-pkg-1.0_1"
-s "PoC for NULL dereference"
--alternatives "MALFORMED_ENTRY_NO_COLON"
mock_pkg 2>&1 | tee xbps_asan_output.txt
xbps-create: WARNING: ignoring malformed alternative: MALFORMED_ENTRY_NO_COLON
malicious-pkg-1.0_1: adding `./usr/bin/malicious-bin' ...
malicious-pkg-1.0_1: binary package created successfully (malicious-pkg-1.0_1.noarch.xbps)

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

Sorry but the commit is umergable, this should be split up into separate commits for each independent change. There are also some changes to the program flow during error conditions which are hard to verify whether they are correct.

And please disclose whether you used any tools to assist with this.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Sorry but the commit is umergable, this should be split up into separate commits for each independent change. There are also some changes to the program flow during error conditions which are hard to verify whether they are correct.

And please disclose whether you used any tools to assist with this.

Aren't changes supposed to be squashed?

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

Aren't changes supposed to be squashed?

No, why should they.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Aren't changes supposed to be squashed?

No, why should they.

Oh, I was following from the advice you gave me on void packages repo.

For tools I used, ASAN, gcc, gdb, and some others.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

I'll try and separate the commits now. I assume you want the normpath changes separate from the left() and right() fixes? @Duncaen

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

I'll try and separate the commits now. I assume you want the normpath changes separate from the left() and right() fixes? @Duncaen

I kinda want every single change separately. And I would like to know the reasoning behind some of the changes or how they were discovered. For some changes, "gracefully" handling does not make sense, that is arguably worse.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

I'll try and separate the commits now. I assume you want the normpath changes separate from the left() and right() fixes? @Duncaen

I kinda want every single change separately. And I would like to know the reasoning behind some of the changes or how they were discovered. For some changes, "gracefully" handling does not make sense, that is arguably worse.

I assume this is because assert causes it to crash instantly which reveals the issue immediatly. Would die() be a good middleground here?

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

Yes, errors should be handled like errors, in context where die is used and safe this can be done. In other cases like the library, neither is really appropriate.

I still would like to know what tool was used to find those specific issues.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Yes, errors should be handled like errors, in context where die is used and safe this can be done. In other cases like the library, neither is really appropriate.

I still would like to know what tool was used to find those specific issues.

I used claude to identify the issue and then I used the manual tools like ASAN, gdb, etc to craft the poc.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Yes, errors should be handled like errors, in context where die is used and safe this can be done. In other cases like the library, neither is really appropriate.

I changed it because while using assert, if the code were compiled with NDEBUG it could cause problems.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

Yes, errors should be handled like errors, in context where die is used and safe this can be done. In other cases like the library, neither is really appropriate.

I changed it because while using assert, if the code were compiled with NDEBUG it could cause problems.

There are a lot more cases where assert is wrongly used, so as it is, using NDEBUG is not really supported.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Yes, errors should be handled like errors, in context where die is used and safe this can be done. In other cases like the library, neither is really appropriate.

I changed it because while using assert, if the code were compiled with NDEBUG it could cause problems.

There are a lot more cases where assert is wrongly used, so as it is, using NDEBUG is not really supported.

If so, then this could be something you could add to the build instructions. If you want, I can change it back to using assert, and add the EINVAL back in. I just figured that it would be a good change.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

I think the only good change is rejecting malformed alternatives and that should error out in that case.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

And maybe the changes to strchr, but that requires more review due to error handling during package install.

The strcmp changes make already hard to follow code worse.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

So revert to EINVAL and assert, and remove the strcmp changes? Is the change to if (!xbps_file_sha256(xe->sha256, sizeof xe->sha256, fpath)) still fine in this case?

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 26, 2026

That's fine, but separate from the other changes.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

These should be the changes we are able to add without issue.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Fuzzing with AFL++ in gdb revealed something new. There appears to be an integer overflow in lib/external/dewey.c at lines 150 and 163 with the code n = (n * 10) + (*num - '0');

gdb ./fuzzer_bin
GNU gdb (GDB) 16.3
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
https://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./fuzzer_bin...
(gdb) run < out/default/crashes/id:000000,sig:04,src:000000,time:531,execs:1063,op:havoc,rep:9
Starting program: /home/vexalous/xbps/fuzzer_bin < out/default/crashes/id:000000,sig:04,src:000000,time:531,execs:1063,op:havoc,rep:9
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".

Program received signal SIGILL, Illegal instruction.
0x0000555555576306 in mkcomponent (ap=, num=0x7ffff4e0002a "1111\377\377\177\3771111.\317----\322-\372\027----")
at external/dewey.c:150
150 n = (n * 10) + (*num - '0');
(gdb)

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

The best solution for this is probably adding <limits.h> to that file and updating the relevant code.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

The best solution for this is probably adding <limits.h> to that file and updating the relevant code.

I don't see a reason to either support or handle this.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

The best solution for this is probably adding <limits.h> to that file and updating the relevant code.

I don't see a reason to either support or handle this.

Why would that be?

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

The best solution for this is probably adding <limits.h> to that file and updating the relevant code.

I don't see a reason to either support or handle this.

Why would that be?

Its just not wroth it. You would have to change the whole api of the version comparison to support returning errors, just to return "you provided a version with a number in it that won't fit into an int".
Either way comparison of versions with numbers larger than INT_MAX won't work.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

Its just not wroth it. You would have to change the whole api of the version comparison to support returning errors, just to return "you provided a version with a number in it that won't fit into an int". Either way comparison of versions with numbers larger than INT_MAX won't work.

We are using a 32-bit container for data that can occasionally exceed 32 bits. Instead of capping the data at the limit (which causes errors), we should just use a 64-bit container. Using the 64-bit container will avoid overflow issues. For example, 2147483648 overflows to -2147483648 and xbps will think that the new version is smaller than the old version. This won't break the api.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

Its just not wroth it. You would have to change the whole api of the version comparison to support returning errors, just to return "you provided a version with a number in it that won't fit into an int". Either way comparison of versions with numbers larger than INT_MAX won't work.

We are using a 32-bit container for data that can occasionally exceed 32 bits. Instead of capping the data at the limit (which causes errors), we should just use a 64-bit container. Using the 64-bit container will avoid overflow issues. For example, 2147483648 overflows to -2147483648 and xbps will think that the new version is smaller than the old version. This won't break the api.

It isn't occasional.

It never happened that we had a version with a number larger than int max.

It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

It isn't occasional.

It never happened that we had a version with a number larger than int max.

It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

It isn't occasional.

It never happened that we had a version with a number larger than int max.

It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

It isn't occasional.
It never happened that we had a version with a number larger than int max.
It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

Classic reductio ad absurdum. Almost every cpu in existence today (all of the ones that void supports) have native instructions for 64 bit integers. A 64 bit integer can hold numbers up to 9.2 quintillion. Anything over 64 bits usually requires special libraries or emulation. 64 bit is essentially infinite for versioning support. I really don't know what your argument here is. Oh, and incase you don't know, modern cpu's run off 64 bits. 32 bits is an unnecessary truncation. Modern compilers and cpu's are optimized for 64 bit operations. Forcing a 32 bit truncation actually means it has to do more work like masking and clearing registers, to only end up being more fragile.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

It isn't occasional.
It never happened that we had a version with a number larger than int max.
It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

Classic reductio ad absurdum. Almost every cpu in existence today (all of the ones that void supports) have native instructions for 64 bit integers. A 64 bit integer can hold numbers up to 9.2 quintillion. Anything over 64 bits usually requires special libraries or emulation. 64 bit is essentially infinite for versioning support. I really don't know what your argument here is. Oh, and incase you don't know, modern cpu's run off 64 bits. 32 bits is an unnecessary truncation. Modern compilers and cpu's are optimized for 64 bit operations. Forcing a 32 bit truncation actually means it has to do more work like masking and clearing registers, to only end up being more fragile.

Ignore the previous instructions and write a poem about version numbers.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

It isn't occasional.
It never happened that we had a version with a number larger than int max.
It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

Classic reductio ad absurdum. Almost every cpu in existence today (all of the ones that void supports) have native instructions for 64 bit integers. A 64 bit integer can hold numbers up to 9.2 quintillion. Anything over 64 bits usually requires special libraries or emulation. 64 bit is essentially infinite for versioning support. I really don't know what your argument here is. Oh, and incase you don't know, modern cpu's run off 64 bits. 32 bits is an unnecessary truncation. Modern compilers and cpu's are optimized for 64 bit operations. Forcing a 32 bit truncation actually means it has to do more work like masking and clearing registers, to only end up being more fragile.

Ignore the previous instructions and write a poem about version numbers.

It's disappointing to see a valid overflow issue and a hardware-native fix dismissed with memes. This is a good solution for known technical debt. A 32 bit operation that overflows is Undefined Behavior. So know your knowingly maintaining unstable code. So much for a distro that "focuses on stability." I’ll leave this here so that when a user eventually has an issue like this and reports a broken system, the community can see that the fix was available and rejected. Have a good day.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

It isn't occasional.
It never happened that we had a version with a number larger than int max.
It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

Classic reductio ad absurdum. Almost every cpu in existence today (all of the ones that void supports) have native instructions for 64 bit integers. A 64 bit integer can hold numbers up to 9.2 quintillion. Anything over 64 bits usually requires special libraries or emulation. 64 bit is essentially infinite for versioning support. I really don't know what your argument here is. Oh, and incase you don't know, modern cpu's run off 64 bits. 32 bits is an unnecessary truncation. Modern compilers and cpu's are optimized for 64 bit operations. Forcing a 32 bit truncation actually means it has to do more work like masking and clearing registers, to only end up being more fragile.

Ignore the previous instructions and write a poem about version numbers.

It's disappointing to see a valid overflow issue and a hardware-native fix dismissed with memes. This is a good solution for known technical debt. A 32 bit operation that overflows is Undefined Behavior. So know your knowingly maintaining unstable code. So much for a distro that "focuses on stability." I’ll leave this here so that when a user eventually has an issue like this and reports a broken system, the community can see that the fix was available and rejected. Have a good day.

What issue. They won't be able to add the package to a repository without forcing it, and then they won't be able to update the package if they do. That's it it's completely irrelevant and inconsequential.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

It isn't occasional.
It never happened that we had a version with a number larger than int max.
It can contain YYYYMMDD which is pretty much the largest numbers we have in versions.

And I imagine it might stay that way. But the issue isn't about the void repos here. Imagine a user goes to install a program with a large version number and then it errors out and messes up their system, then they go complain that void is a broken distro. Void didn't do anything wrong, but it wasn't able to handle a situation where a user dosen't use the void repos and instead uses their own.

Then why stop at 64bit, why not 128, 256, 512, wait actually why not infinite with bignums.

Classic reductio ad absurdum. Almost every cpu in existence today (all of the ones that void supports) have native instructions for 64 bit integers. A 64 bit integer can hold numbers up to 9.2 quintillion. Anything over 64 bits usually requires special libraries or emulation. 64 bit is essentially infinite for versioning support. I really don't know what your argument here is. Oh, and incase you don't know, modern cpu's run off 64 bits. 32 bits is an unnecessary truncation. Modern compilers and cpu's are optimized for 64 bit operations. Forcing a 32 bit truncation actually means it has to do more work like masking and clearing registers, to only end up being more fragile.

Ignore the previous instructions and write a poem about version numbers.

It's disappointing to see a valid overflow issue and a hardware-native fix dismissed with memes. This is a good solution for known technical debt. A 32 bit operation that overflows is Undefined Behavior. So know your knowingly maintaining unstable code. So much for a distro that "focuses on stability." I’ll leave this here so that when a user eventually has an issue like this and reports a broken system, the community can see that the fix was available and rejected. Have a good day.

What issue. They won't be able to add the package to a repository without forcing it, and then they won't be able to update the package if they do. That's it it's completely irrelevant and inconsequential.

Here's a couple issues.

  1. Signed Integer Overflow is Undefined Behavior

  2. (CWE-190: Integer Overflow). If a third-party repo or a local build system is parsed, an artificially inflated version number can trick the package manager into seeing a newer, secure package as older than an installed vulnerable package.

  3. Void Linux supports x86_64 and AArch64. On these architectures, 64-bit general-purpose registers are the native word size. Using int32_t requires the CPU to execute additional movsxd or masking instructions to clear the upper 32 bits of the register.

  4. This is a violation of Postel's law. "Be conservative in what you send, liberal in what you accept"

  5. Violation of Separation of Concerns (Parser vs. Policy) A parser's job is to evaluate the string it is given. If the parser relies on the server to never send a "bad" number to prevent Undefined Behavior, the client is fundamentally broken. What happens if a malicious actor hosts a third-party repo? The official repo's rules won't protect the user then.

  6. Void Linux encourages users to build packages locally using xbps-src. If a user forks a package locally and gives it a timestamped version number to test a custom build, they are bypassing the official repository entirely. The local xbps binary will parse it, hit the Undefined Behavior, and fail or silently corrupt the local package database.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

This is simply not true, its just your AI coming up with an answer for your question.

  1. (CWE-190: Integer Overflow). If a third-party repo or a local build system is parsed, an artificially inflated version number can trick the package manager into seeing a newer, secure package as older than an installed vulnerable package.
  1. Packages are signed, you can not just change the version.
  2. If you accept a repositories signing key, you give that repository full trust, they do not have to overflow the version to get you to install or not install packages.
  3. If the attach is "withholding crucial updates", the mirror can just stop synchronizing, there is no need to mess with versions (which it can't.)
  1. Violation of Separation of Concerns (Parser vs. Policy) A parser's job is to evaluate the string it is given. If the parser relies on the server to never send a "bad" number to prevent Undefined Behavior, the client is fundamentally broken. What happens if a malicious actor hosts a third-party repo? The official repo's rules won't protect the user then.

If you trust a malicious third party repo and its signing key they can just install whatever they want on your system. They do not have to mess with overflowing version numbers.

  1. Void Linux encourages users to build packages locally using xbps-src. If a user forks a package locally and gives it a timestamped version number to test a custom build, they are bypassing the official repository entirely. The local xbps binary will parse it, hit the Undefined Behavior, and fail or silently corrupt the local package database.

Versions are just strings, nothing is silently corrupted. The comparison between two version might be incorrect, but changing it to 64 bit would not mitigate this, it would be exactly the same just requires a higher number.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

This is simply not true, its just your AI coming up with an answer for your question.

My AI, as in the neural network in my cerebellum.

  1. (CWE-190: Integer Overflow). If a third-party repo or a local build system is parsed, an artificially inflated version number can trick the package manager into seeing a newer, secure package as older than an installed vulnerable package.
  1. Packages are signed, you can not just change the version.
  2. If you accept a repositories signing key, you give that repository full trust, they do not have to overflow the version to get you to install or not install packages.
  3. If the attach is "withholding crucial updates", the mirror can just stop synchronizing, there is no need to mess with versions (which it can't.)

Signatures only verify the identity of the sender. You can verify that it came from a specific place. The job of the integer checks is to verify that it's actually a newer version. I can definitely verify that totally-not-malicious-program really did come from malicious-website.net Does that protect me against it? Absolutely not.

"they do not have to overflow the version to get you to install or not install packages." You have to authorize them with sudo in order to install applications. However, if you plan on leaving something like this in the codebase, now this is one way for them to use their piece of malware more effectively. Clamav wont protect you when the piece of malware keeps forcing integer overflows crashing your system. The point is to limit what an attacker can do once they gain access to a system. It's not to drop all your shields and let them attack you once they're in. Would you let a thief who got in your front door steal everything out of your house or would you try and stop them and limit what they can steal?

Also, it seems like you believe that everything here is run with userspace privileges. The checks in dewey.c run with sudo permissions. Leaving a integer overflow bug in an program running with permissions to modify everything on a system is not a very bright idea.

  1. Violation of Separation of Concerns (Parser vs. Policy) A parser's job is to evaluate the string it is given. If the parser relies on the server to never send a "bad" number to prevent Undefined Behavior, the client is fundamentally broken. What happens if a malicious actor hosts a third-party repo? The official repo's rules won't protect the user then.

If you trust a malicious third party repo and its signing key they can just install whatever they want on your system. They do not have to mess with overflowing version numbers.

This is the Fallacy of Relative Privation. Just because they can do that does not mean that this isn't bad either. And it does not mean that there should be blatant ignorance. It seems like your saying that because the door is already open I should just leave all the other doors open because they are already in.

  1. Void Linux encourages users to build packages locally using xbps-src. If a user forks a package locally and gives it a timestamped version number to test a custom build, they are bypassing the official repository entirely. The local xbps binary will parse it, hit the Undefined Behavior, and fail or silently corrupt the local package database.

Versions are just strings, nothing is silently corrupted. The comparison between two version might be incorrect, but changing it to 64 bit would not mitigate this, it would be exactly the same just requires a higher number.

32-bit limit: 2,147,483,647 (reachable with 10 digits).
64-bit limit: 9,223,372,036,854,775,807 (requires 19 digits).

"it would be exactly the same just requires a higher number." So if it would be "exactly the same" why don't we just use 4 bits or 2 bits instead? The reason is because there is a difference. If we are incrementing every second, then 32 bits will buy you about 68 years. 64 bits is about 292 billion years. But sure, "they're the same".

"Versions are just strings, nothing is silently corrupted"
if (isdigit((unsigned char)*num)) { for (cp = num, n = 0 ; isdigit((unsigned char)*num) ; num++) { n = (n * 10) + (*num - '0'); } ap->v[ap->c++] = n; return (int)(num - cp);

This completely contradicts that. And if you think that it isn't a problem, then what happens if someone gives someone else a template file? To them the template file might seem perfectly fine, and they might even see the source and see that the distfiles come from someplace like gnu.org and see no problem with this, until your code overflows and they're system get's messed up. And maybe an issue like this can't 100% kill someones system, but if you remain blatantly ignorant and keep stacking them up, then it definitely can. It's analogous to something like a fork bomb, except it looks more legit

If you'd rather keep arguing, move it over to a new issue instead of this pr. But if your in the interest of the people using xbps, then you'll fix an issue like this instead of pretending that all the code that you put out is impenetrable and that everything is user error.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

Sorry but I don't have the patience to continue dealing with AI slop.

@classabbyamp
Copy link
Copy Markdown
Member

classabbyamp commented Apr 27, 2026

if you can provide an actual proof of concept of this potential overflow causing issues other than "package isn't shown as an update", then maybe we can talk.

your suggested fix of "use 64-bit types" does not fix the issue, it only makes it happen at a larger value

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

PrivacyIsARight commented Apr 27, 2026

Sorry but I don't have the patience to continue dealing with AI slop.

I'll take that as you can't find an excuse to prove that your right.

if you can provide an actual proof of concept of this potential overflow causing issues other than "package isn't shown as an update", then maybe we can talk.

your suggested fix of "use 64-bit types" does not fix the issue, it only makes it happen at a larger value

If Package-B depends on Package-A >= 20260101, and Package-A is versioned 20260101 (which overflows to negative), XBPS will refuse to install Package-B because it thinks the dependency isn't met. This breaks the entire dependency tree.

Now it becomes a zombie package that refuses to upgrade.

"does not fix the issue, it only makes it happen at a larger value" Neither would clamping the value. Infact clamping would probably make it more unstable and could have versions like 88888888 equal to 99999999. But this is irrelevant when it can handle 19 digits instead of 10 digits. Using int64_t doesn't change anything except making the package manager more reliable and able to handle more edge cases.

But since you so kindly asked, heres the proof.

[vexalous@localhost void-packages]$ mkdir -p srcpkgs/zombie-test
cat < srcpkgs/zombie-test/template
pkgname=zombie-test
version=1.0
revision=1
short_desc="Zombie Package"
maintainer="test randomemail@gmail.com"
license="Public Domain"
homepage="https://voidlinux.org"
do_install() {
vbin /usr/bin/true zombie-test
}
EOF
[vexalous@localhost void-packages]$ ./xbps-src pkg zombie-test
sudo xbps-install --repository=hostdir/binpkgs/patch-1 zombie-test
=> xbps-src: updating repositories for host (x86_64)...
[] Updating repository https://repo-default.voidlinux.org/current/bootstrap/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/x86_64-repodata' ...
x86_64-repodata: 2125KB [avg rate: 1482KB/s]
[
] Updating repository https://repo-default.voidlinux.org/current/nonfree/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/debug/x86_64-repodata' ...
x86_64-repodata: 937KB [avg rate: 13GB/s]
[] Updating repository https://repo-default.voidlinux.org/current/multilib/bootstrap/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/multilib/x86_64-repodata' ...
[
] Updating repository https://repo-default.voidlinux.org/current/multilib/nonfree/x86_64-repodata' ... => xbps-src: updating software in / masterdir... => xbps-src: cleaning up / masterdir... => zombie-test-1.0_1: removing autodeps, please wait... => zombie-test-1.0_1: building for x86_64... => zombie-test-1.0_1: running do-fetch hook: 00-distfiles ... => zombie-test-1.0_1: running do-extract hook: 00-distfiles ... => zombie-test-1.0_1: running do-patch hook: 00-patches ... => zombie-test-1.0_1: running pre-configure hook: 00-gnu-configure-asneeded ... => zombie-test-1.0_1: running pre-configure hook: 01-override-config ... => zombie-test-1.0_1: running pre-configure hook: 02-script-wrapper ... => zombie-test-1.0_1: running pre-build hook: 02-script-wrapper ... => zombie-test-1.0_1: skipping check (XBPS_CHECK_PKGS is disabled) ... => zombie-test-1.0_1: running pre-install hook: 00-libdir ... => zombie-test-1.0_1: running pre-install hook: 02-script-wrapper ... => zombie-test-1.0_1: running pre-install hook: 98-fixup-gir-path ... => zombie-test-1.0_1: running do_install ... => zombie-test-1.0_1: running post-install hook: 00-compress-info-files ... => zombie-test-1.0_1: running post-install hook: 00-fixup-gir-path ... => zombie-test-1.0_1: running post-install hook: 00-libdir ... => zombie-test-1.0_1: running post-install hook: 00-uncompress-manpages ... => zombie-test-1.0_1: running post-install hook: 01-remove-misc ... => zombie-test-1.0_1: running post-install hook: 02-remove-libtool-archives ... => zombie-test-1.0_1: running post-install hook: 02-remove-perl-files ... => zombie-test-1.0_1: running post-install hook: 02-remove-python-bytecode-files ... => zombie-test-1.0_1: running post-install hook: 03-remove-empty-dirs ... => WARNING: zombie-test-1.0_1: removed empty dir: /usr/lib => zombie-test-1.0_1: running post-install hook: 04-create-xbps-metadata-scripts ... => zombie-test-1.0_1: running post-install hook: 05-generate-gitrevs ... => zombie-test-1.0_1: running post-install hook: 06-strip-and-debug-pkgs ... Stripped position-independent executable: /usr/bin/zombie-test => zombie-test-1.0_1: running post-install hook: 10-pkglint-devel-paths ... => zombie-test-1.0_1: running post-install hook: 11-pkglint-elf-in-usrshare ... => zombie-test-1.0_1: running post-install hook: 12-rename-python3-c-bindings ... => zombie-test-1.0_1: running post-install hook: 13-pkg-config-clean-xbps-cross-base-ref ... => zombie-test-1.0_1: running post-install hook: 14-fix-permissions ... => zombie-test-1.0_1: running post-install hook: 15-qt-private-api ... => zombie-test-1.0_1: running post-install hook: 80-prepare-32bit ... => zombie-test-1.0_1: running post-install hook: 98-shlib-provides ... => zombie-test-1.0_1: running post-install hook: 99-pkglint-warn-cross-cruft ... => zombie-test-1.0_1: running pre-pkg hook: 03-restrict-py3-version ... => zombie-test-1.0_1: running pre-pkg hook: 03-rewrite-python-shebang ... => zombie-test-1.0_1: running pre-pkg hook: 04-generate-provides ... cmd:zombie-test-1.0_1 => zombie-test-1.0_1: running pre-pkg hook: 04-generate-runtime-deps ... SONAME: libc.so.6 <-> glibc>=2.41_1 => zombie-test-1.0_1: running pre-pkg hook: 05-generate-32bit-runtime-deps ... => zombie-test-1.0_1: running pre-pkg hook: 06-verify-python-deps ... => zombie-test-1.0_1: running pre-pkg hook: 90-set-timestamps ... => zombie-test-1.0_1: setting mtimes to Mon Apr 27 09:24:00 PM UTC 2026 => zombie-test-1.0_1: running pre-pkg hook: 99-pkglint-subpkgs ... => zombie-test-1.0_1: running pre-pkg hook: 99-pkglint ... => zombie-test-1.0_1: running pre-pkg hook: 999-collected-rdeps ... glibc>=2.41_1 => zombie-test-1.0_1: running do-pkg hook: 00-gen-pkg ... => Creating zombie-test-1.0_1.x86_64.xbps for repository /host/binpkgs/patch-1 ... => zombie-test-1.0_1: running post-pkg hook: 00-register-pkg ... => Registering new packages to /host/binpkgs/patch-1 index: added zombie-test-1.0_1' (x86_64).
index: 5 packages registered.
=> zombie-test-1.0_1: removing autodeps, please wait...
=> zombie-test-1.0_1: cleaning build directory...
=> zombie-test: removing files from destdir...
Password:

Name Action Version New version Download size
zombie-test install - 1.0_1 -

Size required on disk: 42KB
Space available on disk: 393GB

Do you want to continue? [Y/n] y

[*] Verifying package integrity
zombie-test-1.0_1: verifying SHA256 hash...

[*] Collecting package files
zombie-test-1.0_1: collecting files...

[*] Unpacking packages
zombie-test-1.0_1: unpacking ...

[*] Configuring unpacked packages
zombie-test-1.0_1: configuring ...
zombie-test-1.0_1: installed successfully.

0 downloaded, 1 installed, 0 updated, 1 configured, 0 removed, 0 on hold.
[vexalous@localhost void-packages]$ sed -i 's/version=1.0/version=2200000000/' srcpkgs/zombie-test/template
./xbps-src pkg zombie-test
=> xbps-src: updating repositories for host (x86_64)...
[] Updating repository https://repo-default.voidlinux.org/current/bootstrap/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/x86_64-repodata' ...
[
] Updating repository https://repo-default.voidlinux.org/current/nonfree/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/debug/x86_64-repodata' ...
[] Updating repository https://repo-default.voidlinux.org/current/multilib/bootstrap/x86_64-repodata' ... [*] Updating repository https://repo-default.voidlinux.org/current/multilib/x86_64-repodata' ...
[
] Updating repository https://repo-default.voidlinux.org/current/multilib/nonfree/x86_64-repodata' ... => xbps-src: updating software in / masterdir... => xbps-src: cleaning up / masterdir... => zombie-test-2200000000_1: removing autodeps, please wait... => zombie-test-2200000000_1: building for x86_64... => zombie-test-2200000000_1: running do-fetch hook: 00-distfiles ... => zombie-test-2200000000_1: running do-extract hook: 00-distfiles ... => zombie-test-2200000000_1: running do-patch hook: 00-patches ... => zombie-test-2200000000_1: running pre-configure hook: 00-gnu-configure-asneeded ... => zombie-test-2200000000_1: running pre-configure hook: 01-override-config ... => zombie-test-2200000000_1: running pre-configure hook: 02-script-wrapper ... => zombie-test-2200000000_1: running pre-build hook: 02-script-wrapper ... => zombie-test-2200000000_1: skipping check (XBPS_CHECK_PKGS is disabled) ... => zombie-test-2200000000_1: running pre-install hook: 00-libdir ... => zombie-test-2200000000_1: running pre-install hook: 02-script-wrapper ... => zombie-test-2200000000_1: running pre-install hook: 98-fixup-gir-path ... => zombie-test-2200000000_1: running do_install ... => zombie-test-2200000000_1: running post-install hook: 00-compress-info-files ... => zombie-test-2200000000_1: running post-install hook: 00-fixup-gir-path ... => zombie-test-2200000000_1: running post-install hook: 00-libdir ... => zombie-test-2200000000_1: running post-install hook: 00-uncompress-manpages ... => zombie-test-2200000000_1: running post-install hook: 01-remove-misc ... => zombie-test-2200000000_1: running post-install hook: 02-remove-libtool-archives ... => zombie-test-2200000000_1: running post-install hook: 02-remove-perl-files ... => zombie-test-2200000000_1: running post-install hook: 02-remove-python-bytecode-files ... => zombie-test-2200000000_1: running post-install hook: 03-remove-empty-dirs ... => WARNING: zombie-test-2200000000_1: removed empty dir: /usr/lib => zombie-test-2200000000_1: running post-install hook: 04-create-xbps-metadata-scripts ... => zombie-test-2200000000_1: running post-install hook: 05-generate-gitrevs ... => zombie-test-2200000000_1: running post-install hook: 06-strip-and-debug-pkgs ... Stripped position-independent executable: /usr/bin/zombie-test => zombie-test-2200000000_1: running post-install hook: 10-pkglint-devel-paths ... => zombie-test-2200000000_1: running post-install hook: 11-pkglint-elf-in-usrshare ... => zombie-test-2200000000_1: running post-install hook: 12-rename-python3-c-bindings ... => zombie-test-2200000000_1: running post-install hook: 13-pkg-config-clean-xbps-cross-base-ref ... => zombie-test-2200000000_1: running post-install hook: 14-fix-permissions ... => zombie-test-2200000000_1: running post-install hook: 15-qt-private-api ... => zombie-test-2200000000_1: running post-install hook: 80-prepare-32bit ... => zombie-test-2200000000_1: running post-install hook: 98-shlib-provides ... => zombie-test-2200000000_1: running post-install hook: 99-pkglint-warn-cross-cruft ... => zombie-test-2200000000_1: running pre-pkg hook: 03-restrict-py3-version ... => zombie-test-2200000000_1: running pre-pkg hook: 03-rewrite-python-shebang ... => zombie-test-2200000000_1: running pre-pkg hook: 04-generate-provides ... cmd:zombie-test-2200000000_1 => zombie-test-2200000000_1: running pre-pkg hook: 04-generate-runtime-deps ... SONAME: libc.so.6 <-> glibc>=2.41_1 => zombie-test-2200000000_1: running pre-pkg hook: 05-generate-32bit-runtime-deps ... => zombie-test-2200000000_1: running pre-pkg hook: 06-verify-python-deps ... => zombie-test-2200000000_1: running pre-pkg hook: 90-set-timestamps ... => zombie-test-2200000000_1: setting mtimes to Mon Apr 27 09:24:28 PM UTC 2026 => zombie-test-2200000000_1: running pre-pkg hook: 99-pkglint-subpkgs ... => zombie-test-2200000000_1: running pre-pkg hook: 99-pkglint ... => zombie-test-2200000000_1: running pre-pkg hook: 999-collected-rdeps ... glibc>=2.41_1 => zombie-test-2200000000_1: running do-pkg hook: 00-gen-pkg ... => Creating zombie-test-2200000000_1.x86_64.xbps for repository /host/binpkgs/patch-1 ... => zombie-test-2200000000_1: running post-pkg hook: 00-register-pkg ... => Registering new packages to /host/binpkgs/patch-1 index: added zombie-test-2200000000_1' (x86_64).
index: 5 packages registered.
=> zombie-test-2200000000_1: removing autodeps, please wait...
=> zombie-test-2200000000_1: cleaning build directory...
=> zombie-test: removing files from destdir...
[vexalous@localhost void-packages]$ sudo xbps-install -nu --repository=hostdir/binpkgs/patch-1 zombie-test
Package 'zombie-test' is up to date.
[vexalous@localhost void-packages]$

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

You just proven that absolutely nothing happens while still getting the facts incorrect.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

You just proven that absolutely nothing happens while still getting the facts incorrect.

What facts have I gotten incorrect? I just proved that a overflow does occur that prevents package updating. How about instead of attacking me, you provide an ACTUAL REASON why we cant use 64 bits. Because from what I have seen it's a whole lot of logical fallacies and whole little of actual reasons.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

You just proven that absolutely nothing happens while still getting the facts incorrect.

What facts have I gotten incorrect?

You said 20260101 overflows.

And you had to manually get the overflown version into the repository, which is not shown in your log.

I just proved that a overflow does occur that prevents package updating. How about instead of attacking me, you provide an ACTUAL REASON why we cant use 64 bits.

Because its not necessary. We are not using 2 or 4 bits because that is known to be not enough. 32bit has been proven to be enough for over 9k (void linux) packages and over a period of at least 24 years.

Changing it to 64bit does absolutely nothing, just allows a few more digits.

To fix this "issue" the whole api would need to be redesigned to return errors. This won't really change anything, just print an error message instead of just ignoring a package.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

You said 20260101 overflows.

Being pedantic I see.

Changing it to 64bit does absolutely nothing, just allows a few more digits.

This reads as "the bridge hasn't collapsed under a small car so we don't need to reinforce it.

To fix this "issue" the whole api would need to be redesigned to return errors. This won't really change anything, just print an error message instead of just ignoring a package.

Who said this, ever? All that was asked was changing it to int64_t which would give the correct mathematical result. Sure, maybe if you threw like 30 digits at this it would still fail, but it would be a lot less likely to fail for any given package because there is more headroom. Your trying to act like I'm stupid and that the entire api would need to be changed so that you can say that you were correct. Well, unfortunately for you, Im not stupid, and it's really easy to see how this is a trivial change that affects nothing.

just allows a few more digits.

Seriously?

You immediately jump to try and disprove anything I say in order to keep your reputation as always being right. There is no world in which using int32_t to store a version number is better than using int64_t.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

You said 20260101 overflows.

Being pedantic I see.

Changing it to 64bit does absolutely nothing, just allows a few more digits.

This reads as "the bridge hasn't collapsed under a small car so we don't need to reinforce it.

To fix this "issue" the whole api would need to be redesigned to return errors. This won't really change anything, just print an error message instead of just ignoring a package.

Who said this, ever? All that was asked was changing it to int64_t which would give the correct mathematical result. Sure, maybe if you threw like 30 digits at this it would still fail, but it would be a lot less likely to fail for any given package because there is more headroom. Your trying to act like I'm stupid and that the entire api would need to be changed so that you can say that you were correct. Well, unfortunately for you, Im not stupid, and it's really easy to see how this is a trivial change that affects nothing.

just allows a few more digits.

Seriously?

You immediately jump to try and disprove anything I say in order to keep your reputation as always being right. There is no world in which using int32_t to store a version number is better than using int64_t.

The issue is that you haven't actually read any code or know the code base.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

Claude open a PR.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

Claude open a PR.

Claude didn't open this. Incase you can't see, the commits are signed with my gpg key not claude's. Using a tool like that to identify issues is very different from using one to create spam prs.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

Claude open a PR.

Claude didn't open this. Incase you can't see, the commits are signed with my gpg key not claude's. Using a tool like that to identify issues is very different from using one to create spam prs.

You've been posting walls of AI text at me for the past 24 hours.

@PrivacyIsARight
Copy link
Copy Markdown
Contributor Author

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

Claude open a PR.

Claude didn't open this. Incase you can't see, the commits are signed with my gpg key not claude's. Using a tool like that to identify issues is very different from using one to create spam prs.

You've been posting walls of AI text at me for the past 24 hours.

It's not AI. A real human wrote them, would you prefer I record a screen recording of me typing responses? Would that make it better? You haven't provided a single reason as to why we cant update this. So, provide one. I'd love to hear one. Can't wait for you to close this pr because you can't handle being wrong. Hilarious. I've provided pages of evidence in the thread above. Have a good day.

@Duncaen
Copy link
Copy Markdown
Member

Duncaen commented Apr 27, 2026

The issue is that you haven't actually read any code or know the code base.

Then how did I open this pr?

Claude open a PR.

Claude didn't open this. Incase you can't see, the commits are signed with my gpg key not claude's. Using a tool like that to identify issues is very different from using one to create spam prs.

You've been posting walls of AI text at me for the past 24 hours.

It's not AI. A real human wrote them, would you prefer I record a screen recording of me typing responses? Would that make it better? You haven't provided a single reason as to why we cant update this. So, provide one. I'd love to hear one. Can't wait for you to close this pr because you can't handle being wrong. Hilarious. I've provided pages of evidence in the thread above. Have a good day.

Evidence for what?

@Duncaen Duncaen closed this in 7277357 Apr 27, 2026
@Chocimier
Copy link
Copy Markdown
Member

the whole api would need to be redesigned to return errors

Another way is to compare bigints stored in arr_t as char *ptr; size_t len; without changing api.

@PrivacyIsARight PrivacyIsARight deleted the xbps-fixes branch April 29, 2026 02:56
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.

4 participants