Skip to content

Conversation

@smaye81
Copy link
Contributor

@smaye81 smaye81 commented Apr 1, 2025

This beefs up the validation for the following:

IP address (v4 and v6)
IP prefix (v4 and v6)
Hostname / Port

@smaye81 smaye81 changed the base branch from main to sayers/validation_upgrades April 1, 2025 16:03
@smaye81 smaye81 requested review from pkwarren and timostamm April 1, 2025 16:05
@smaye81
Copy link
Contributor Author

smaye81 commented Apr 1, 2025

@pkwarren reverted back to JDK 8.

return !portRequired && isIP(str.substring(1, end), 6);
} else if (endPlus == splitIdx) { // port
return isIP(str.substring(1, end), 6) && isPort(str.substring(splitIdx + 1));
} else { // malformed
Copy link
Member

Choose a reason for hiding this comment

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

nit: General code style but would prefer we remove the else here and just return as before.

private static boolean validatePort(String value) {
// Returns true if the string is a valid port for isHostAndPort.
private static boolean isPort(String str) {
if (str.length() == 0) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (str.length() == 0) {
if (str.isEmpty()) {

int portNum = Integer.parseInt(value);
return portNum >= 0 && portNum <= 65535;
int val = Integer.parseInt(str);

Copy link
Member

Choose a reason for hiding this comment

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

nit: Can remove the extra space here and below before the return.

return val <= 65535;

} catch (NumberFormatException nfe) {
// Error converting to number
Copy link
Member

Choose a reason for hiding this comment

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

Can remove this comment.

return true;
private static boolean isIP(String addr, long ver) {
if (ver == 6L) {
return new Ipv6(addr).address();
Copy link
Member

Choose a reason for hiding this comment

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

This is not very idiomatic Java here - having to create an empty object then calling a method on it to determine if it is valid.

I think we should make these functions like isIPv4 and isIPv6 that minimize allocations and state if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, this is where the nuance of trying to stay consistent comes into play. This allocation is done across impls, so should we refactor those also? cc @timostamm

private boolean prefixLength() {
int start = this.index;

while (true) {
Copy link
Member

Choose a reason for hiding this comment

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

The condition on line 756 should be moved into the while here.

}

String str = this.str.substring(start, this.index);
if (str.length() == 0) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (str.length() == 0) {
if (str.isEmpty()) {

return true;

} catch (NumberFormatException nfe) {
// Error converting to number
Copy link
Member

Choose a reason for hiding this comment

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

Can remove this.

addr = str.toAddress();
} catch (Exception e) {
int val = Integer.parseInt(str);

Copy link
Member

Choose a reason for hiding this comment

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

Lots of extra whitespace in here that isn't improving readability - I'd remove the majority of this.

*/
private boolean digit() {
char c = this.str.charAt(this.index);
if ('0' <= c && c <= '9') {
Copy link
Member

Choose a reason for hiding this comment

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

We've got lots of places in here that could benefit from a static boolean isDigit(char c) helper to simplify code.

return BoolT.False;
}
return Types.boolOf(validateIP(address, rhs.intValue()));
return Types.boolOf(isIP(address, rhs.intValue()));
Copy link
Member

Choose a reason for hiding this comment

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

Is the check for address.isEmpty() still necessary?

Same for other places.

Comment on lines 452 to 454
* <p>The host can be one of: - An IPv4 address in dotted decimal format, for example
* "192.168.0.1". - An IPv6 address enclosed in square brackets, for example "[::1]". - A
* hostname, for example "example.com".
Copy link
Member

Choose a reason for hiding this comment

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

Should use <ul> for the list:

Suggested change
* <p>The host can be one of: - An IPv4 address in dotted decimal format, for example
* "192.168.0.1". - An IPv6 address enclosed in square brackets, for example "[::1]". - A
* hostname, for example "example.com".
* <p>The host can be one of:
* <ul>
* <li>An IPv4 address in dotted decimal format, for example "192.168.0.1".</li>
* <li>An IPv6 address enclosed in square brackets, for example "[::1]".</li>
* <li>A hostname, for example "example.com".</li>
* </ul>

*
* @param host The input string to validate as a hostname.
* @return {@code true} if the input string is a valid hostname, {@code false} otherwise.
* <p>A valid hostname follows the rules below: - The name consists of one or more labels,
Copy link
Member

Choose a reason for hiding this comment

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

Needs a <ul>

Comment on lines 706 to 710
* <p>Returns 0 if no address was parsed successfully.
*/
int getBits() {
if (this.octets.size() != 4) {
return -1;
Copy link
Member

Choose a reason for hiding this comment

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

Documented to return 0, but returns -1.

*
* <p>Method parses the rule:
*
* <p>DIGIT = %x30-39 ; 0-9
Copy link
Member

Choose a reason for hiding this comment

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

Can we use <pre> for ABNF rules?

Suggested change
* <p>DIGIT = %x30-39 ; 0-9
* <pre>DIGIT = %x30-39 ; 0-9</pre>

// dotted notation successfully parsed as IPv4
@Nullable private Ipv4 dottedAddr;
private boolean zoneIDFound;
// 0 -128
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// 0 -128
// 0 - 128

@Nullable private Ipv4 dottedAddr;
private boolean zoneIDFound;
// 0 -128
private long prefixLen;
Copy link
Member

Choose a reason for hiding this comment

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

Why a long if we're only ever assign values between 0 and 128?

* <p>The same principle applies to IPv4 addresses. "192.168.1.0/24" designates the first 24 bits
* of the 32-bit IPv4 as the network prefix.
*/
static boolean isIPPrefix(String str, long version, boolean strict) {
Copy link
Member

Choose a reason for hiding this comment

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

Should be private like the other members.

Comment on lines 703 to 704
* <p>Note Java does not support unsigned numeric types, so to handle unsigned 32-bit values, we
* need to use a 64-bit long type instead of the 32-bit (signed) Integer type.
Copy link
Member

Choose a reason for hiding this comment

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

Documented to use long, but returns an int.

api(libs.protobuf.java)
implementation(enforcedPlatform(libs.cel))
implementation(libs.cel.core)
implementation(libs.guava)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually can't remove Guava. It's used in a bunch of places after looking more in-depth.

@smaye81 smaye81 requested review from pkwarren and timostamm April 2, 2025 20:21
@smaye81
Copy link
Contributor Author

smaye81 commented Apr 2, 2025

@timostamm @pkwarren think i addressed most comments. lmk if I missed anything.

@smaye81 smaye81 merged commit 5a6c681 into sayers/validation_upgrades Apr 3, 2025
3 checks passed
@smaye81 smaye81 deleted the sayers/is_ip branch April 3, 2025 19:31
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