Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #16944: Invalid filtering of IPv6 with FILTER_FLAG_NO_RES_RANGE #17111

Open
wants to merge 10 commits into
base: PHP-8.3
Choose a base branch
from

Conversation

derickr
Copy link
Member

@derickr derickr commented Dec 10, 2024

It also refactors the code to use the actual tables from RFC 6890, and fixed other bugs with these ranges that were introduced with #7893

@derickr
Copy link
Member Author

derickr commented Dec 10, 2024

/cc @nielsdos @nicolas-grekas — It makes most sense to review this commit-by-commit.

Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

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

This is much much nicer, thanks a lot!

*private = false;

if (ip[0] == 0) {
/* RFC 1122 - This host on this network */
Copy link
Member

Choose a reason for hiding this comment

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

The errata for RFC6890 changes this, see https://www.rfc-editor.org/errata_search.php?rfc=6890&rec_status=1&presentation=records
Should instead be: /* RFC 0791 - This network */.

Copy link
Member Author

Choose a reason for hiding this comment

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

It actually splits up the record into two, so I've made this change instead:

 }
 /* }}} */
 
-/* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
-static bool ipv4_get_status_flags(int ip[8], bool *global, bool *reserved, bool *private)
+/* From the tables in RFC 6890 - Special-Purpose IP Address Registriesi
+ * Including errata: https://www.rfc-editor.org/errata_search.php?rfc=6890&rec_status=1 */
+static bool ipv4_get_status_flags(const int ip[8], bool *global, bool *reserved, bool *private)
 {
        *global = false;
        *reserved = false;
        *private = false;
 
        if (ip[0] == 0) {
+               /* RFC 0791 - This network */
+               *reserved = true;
+       } else if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
                /* RFC 1122 - This host on this network */
                *reserved = true;
        } else if (ip[0] == 10) {

Copy link
Member

Choose a reason for hiding this comment

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

Seems good to me. The compiler will optimize that anyway so it's okay to be verbose 🙂

*private = true;
} else if (ip[0] == 192 && ip[1] == 0 && ip[2] == 0) {
/* RFC 6890 - IETF Protocol Assignments */
} else if (ip[0] == 192 && ip[1] >= 0 && ip[1] <= 31) {
Copy link
Member

Choose a reason for hiding this comment

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

The range is 192.0.0.0/29. So this seems wrong because it is 192.0.0.0 until 192.0.0.7, because only the 3 bottom bits are free to use. So both the range and indices of the ip in this check are not correct.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! It looks like the original code didn't even check for this one.

@@ -869,6 +869,106 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8])
}
/* }}} */

/* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
static bool ipv4_get_status_flags(int ip[8], bool *global, bool *reserved, bool *private)
Copy link
Member

Choose a reason for hiding this comment

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

Could be const int ip[8] in theory, but doesn't matter much.

@nielsdos
Copy link
Member

Also note that this should target branch PHP-8.3, see https://externals.io/message/125995

Copy link
Member Author

@derickr derickr left a comment

Choose a reason for hiding this comment

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

Also going to retarget this for PHP 8.3

*private = true;
} else if (ip[0] == 192 && ip[1] == 0 && ip[2] == 0) {
/* RFC 6890 - IETF Protocol Assignments */
} else if (ip[0] == 192 && ip[1] >= 0 && ip[1] <= 31) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! It looks like the original code didn't even check for this one.

*private = false;

if (ip[0] == 0) {
/* RFC 1122 - This host on this network */
Copy link
Member Author

Choose a reason for hiding this comment

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

It actually splits up the record into two, so I've made this change instead:

 }
 /* }}} */
 
-/* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
-static bool ipv4_get_status_flags(int ip[8], bool *global, bool *reserved, bool *private)
+/* From the tables in RFC 6890 - Special-Purpose IP Address Registriesi
+ * Including errata: https://www.rfc-editor.org/errata_search.php?rfc=6890&rec_status=1 */
+static bool ipv4_get_status_flags(const int ip[8], bool *global, bool *reserved, bool *private)
 {
        *global = false;
        *reserved = false;
        *private = false;
 
        if (ip[0] == 0) {
+               /* RFC 0791 - This network */
+               *reserved = true;
+       } else if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
                /* RFC 1122 - This host on this network */
                *reserved = true;
        } else if (ip[0] == 10) {

@derickr derickr changed the base branch from PHP-8.2 to PHP-8.3 December 13, 2024 17:10
/* RFC 1122 - Reserved */
*reserved = true;
} else if (ip[0] == 255 && ip[1] == 255 && ip[2] == 255 && ip[3] == 255) {
/* RFC 0919 - Limited Broadcast */
Copy link
Member

Choose a reason for hiding this comment

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

I did another pass over the PR, and I only have one question for this line here.

RFC8190 updates some parts of RFC6890, but the only change relevant to this RP seems to be "2.2. Updates to the IPv4 Special-Purpose Address Registry". It states:

Limited Broadcast prefix (255.255.255.255/32) - The Reserved-by-
Protocol value has changed from False to True. This change was
made to align the registry with reservation of the limited
broadcast address with Section 7 of [RFC919].

So this likely now needs to set reserved to true.

Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

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

Looks right, thanks

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

Successfully merging this pull request may close these issues.

2 participants