IPv6 alias update crashes with str_repeat() ValueError in PEAR Net_IPv6::uncompress (PHP 8, Spamhaus dropv6 feeds)
-
pfSense 2.9 (release build), pfBlockerNG-devel via pkg. Adding any IPv4 alias works. Creating an IPv6 alias populated with a Spamhaus DROP v6 feed (tried both dropv6.json and dropv6.txt) reproducibly crashes the sync during the IPv6 process, and the crash aborts the whole updateip run BEFORE pf tables commit, so v4 aliases also fail to update on the same run.
Reproducer:
- Create a new v6 alias, e.g. "PRI1_v6", action Deny_Both.
- Add one row: https://www.spamhaus.org/drop/dropv6.txt (or dropv6.json).
- Force Reload IP (or run: /usr/local/bin/php /usr/local/www/pfblockerng/pfblockerng.php updateip).
- Feed downloads 200 OK, "Reload ... completed" is logged, then during the IPv6 processing step the sync dies with:
- PHP ERROR: Uncaught ValueError: str_repeat(): Argument #2 ($times) must be greater than or equal to 0 in /usr/local/share/pear/Net/IPv6.php:684
Stack trace:
#0 /usr/local/share/pear/Net/IPv6.php(684): str_repeat()
#1 /usr/local/share/pear/Net/IPv6.php(1157): Net_IPv6::uncompress()
#2 /usr/local/share/pear/Net/IPv6.php(499): Net_IPv6::_ip2Bin()
#3 /etc/inc/util.inc(1522): Net_IPv6::getAddressType()
#4 /etc/inc/util.inc(1446): is_linklocal()
#5 /usr/local/pkg/pfblockerng/pfblockerng.inc(3679): is_ipaddrv6()
#6 /usr/local/pkg/pfblockerng/pfblockerng.inc(9634): validate_ipv6()
#7 /usr/local/www/pfblockerng/pfblockerng.php(186): sync_package_pfblockerng()Cause (upstream): PEAR Net_IPv6 predates PHP 8's stricter str_repeat() argument validation. Before PHP 8, str_repeat(x, -1) silently returned "" and processing continued; on PHP 8 it raises ValueError. The bug is in Net_IPv6::uncompress() at line 684, where a negative pad width can be computed from an IPv6 string it does not recognise.
Impact: any pfBlockerNG user who adds an IPv6 alias on a modern pfSense build gets no v6 reputation coverage AND their v4 updates stop landing on the same run. Removing the v6 alias fixes both.
Workaround: none for v6 blocking on this box. Removing PRI1_v6 restores v4 sync. v6 stays uncovered until either (a) Net_IPv6.php is patched to guard the str_repeat argument, or (b) validate_ipv6() in pfSense util.inc is changed to guard the input to Net_IPv6::getAddressType(), or (c) pfBlockerNG sanitises input in validate_ipv6() at pfblockerng.inc:9634 before calling is_ipaddrv6() on parsed feed rows.
Happy to test a patch. If someone can point at which feed row is triggering it, I can also open a Spamhaus report if the entry is malformed on their end.
-
@glyph.sh said in IPv6 alias update crashes with str_repeat() ValueError in PEAR Net_IPv6::uncompress (PHP 8, Spamhaus dropv6 feeds):
Hm, not seeing this on 26.x.
Have you tried the release version of pfBlocker?
Oh, and do you have the latest system patches installed+applied? I seem to recall an issue with Suricata IP parsing earlier this year. That won't affect pfB directly but maybe other pfSense functions.
Just to mention it the DROP .txt is to be removed, for other readers:
https://www.spamhaus.org/blocklists/do-not-route-or-peer/#how-it-works -
This post is deleted! -
@SteveITS said in IPv6 alias update crashes with str_repeat() ValueError in PEAR Net_IPv6::uncompress (PHP 8, Spamhaus dropv6 feeds):
@glyph.sh said in IPv6 alias update crashes with str_repeat() ValueError in PEAR Net_IPv6::uncompress (PHP 8, Spamhaus dropv6 feeds):
Hm, not seeing this on 26.x.
Have you tried the release version of pfBlocker?
Oh, and do you have the latest system patches installed+applied? I seem to recall an issue with Suricata IP parsing earlier this year. That won't affect pfB directly but maybe other pfSense functions.
Just to mention it the DROP .txt is to be removed, for other readers:
https://www.spamhaus.org/blocklists/do-not-route-or-peer/#how-it-worksThanks Steve, ran it down on the box, and your .txt-retirement note was the key.
Setup: CE 2.9.0-RELEASE, PHP 8.5.7, pfBlockerNG-devel 3.2.17_1, System Patches installed and the box reports up to date. The fault isn't in pfBlocker itself, it's in the stock pear Net_IPv6 that pfSense's is_ipaddrv6() calls, so the pfBlocker channel doesn't change it.
Trigger: the retired DROPv6 URL now returns an HTML page with a 200, not a CIDR list. pfBlocker saves it and runs the markup through the IPv6 validator line by line, and an HTML token reaches Net_IPv6::uncompress():
/var/db/pfblockerng/original/Spamhaus_Drop_v6_v6.orig:
<!DOCTYPE html><html lang="en" ...><title>The Spamhaus Project</title>...Correction to my first instinct: the obvious one-liner (clamping the str_repeat at IPv6.php:684 with max(0, ...)) is not enough. It stops the reported crash, but the same input then hits a second PHP 8 fatal further down, base_convert() at line 1163 ("An infinite value cannot be converted to base 2"). Patching the EOL pear library one call site at a time is whack-a-mole.
The real fix is at the caller. is_ipaddrv6() already wraps Net_IPv6::checkIPv6() in try/catch, but it calls is_linklocal() first, and is_linklocal() calls Net_IPv6::getAddressType() unguarded, so the exception escapes. Wrapping that one call the same way turns any Net_IPv6 fatal, present or future, into a clean "not a valid address". Verified by replaying the whole HTML page plus overflow addresses through is_ipaddrv6(): zero throws, valid addresses unaffected.
Filed on Redmine with the patch: https://redmine.pfsense.org/issues/17137
Feed side, for anyone else hitting this: move off the deprecated .txt DROP lists to the JSON exports, https://www.spamhaus.org/drop/drop_v4.json and drop_v6.json. pfBlocker parses those fine (its IP regex pulls the cidr out of each line), and the built-in feed catalog already points at them. My v4 coverage was actually intact once I stopped reading the wrong file; the v6 alias just needs the .json URL.
Privacy Policy · Cookie Policy