From 7c39eb8cd28498a17c8e7bb97ab6549986a94640 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Wed, 17 Jul 2019 11:21:02 +0200 Subject: [PATCH 1/6] fix out of bound exception when moving within the tokens list --- src/main/java/emailvalidator4j/lexer/EmailLexer.java | 5 ++++- src/test/java/emailvalidator4j/EmailValidatorTest.java | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/emailvalidator4j/lexer/EmailLexer.java b/src/main/java/emailvalidator4j/lexer/EmailLexer.java index 44c0908..7d56eb3 100644 --- a/src/main/java/emailvalidator4j/lexer/EmailLexer.java +++ b/src/main/java/emailvalidator4j/lexer/EmailLexer.java @@ -62,7 +62,10 @@ public TokenInterface getCurrent() { */ public void next() { this.position ++; - if (!this.isAtEnd()) { + + if (this.isAtEnd()) { + this.position = this.tokens.size(); + } else { this.current = Optional.of(this.tokens.get(this.position)); this.lexedText += this.tokens.get(this.position).getText(); } diff --git a/src/test/java/emailvalidator4j/EmailValidatorTest.java b/src/test/java/emailvalidator4j/EmailValidatorTest.java index 54e8193..ff5022e 100644 --- a/src/test/java/emailvalidator4j/EmailValidatorTest.java +++ b/src/test/java/emailvalidator4j/EmailValidatorTest.java @@ -66,7 +66,7 @@ public static Object[][] invalidEmailProvider() { @UseDataProvider("invalidEmailProvider") public void isInvalidEmail(String email) { EmailValidator validator = new EmailValidator(); - Assert.assertFalse(email + " is an invalid email", validator.isValid(email)); + Assert.assertFalse(email + " should be an invalid email", validator.isValid(email)); } @DataProvider @@ -93,6 +93,7 @@ public static Object[][] validEmailsProvider() { {"\"\\a\"@iana.org"}, {"\"test\\ test\"@iana.org"}, {"\"\"@iana.org"}, + {"\"\"@[]"}/* kind of an edge case, valid for RFC 5322 but address literal is not for 5321 */, {String.format("\"\\%s\"@iana.org", "\"")}, }; } @@ -101,7 +102,7 @@ public static Object[][] validEmailsProvider() { @UseDataProvider("validEmailsProvider") public void isValidEmail(String validEmail) { EmailValidator validator = new EmailValidator(); - Assert.assertTrue(validEmail + " is a valid email", validator.isValid(validEmail)); + Assert.assertTrue(validEmail + " should be a valid email", validator.isValid(validEmail)); } @Test From 86801e46b3bb6ac4d1f5db9a63a0b5301e426bab Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Wed, 17 Jul 2019 11:27:16 +0200 Subject: [PATCH 2/6] fix missing closing bracket in literal domains --- src/main/java/emailvalidator4j/parser/DomainPart.java | 5 +++++ src/test/java/emailvalidator4j/EmailValidatorTest.java | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/emailvalidator4j/parser/DomainPart.java b/src/main/java/emailvalidator4j/parser/DomainPart.java index b8a3dea..b069f19 100755 --- a/src/main/java/emailvalidator4j/parser/DomainPart.java +++ b/src/main/java/emailvalidator4j/parser/DomainPart.java @@ -259,6 +259,11 @@ private void parseLiteralPart() throws InvalidEmail { } } while(!this.lexer.isAtEnd() && !this.lexer.isNextToken(Tokens.CLOSEBRACKET)); + + if (!Tokens.CLOSEBRACKET.equals(this.lexer.getCurrent())) { + throw new ExpectedDTEXT("CLOSEBRACKET"); + } + this.warnings.add(Warnings.RFC5321_ADDRESS_LITERAL); addressLiteral = this.lexer.lexedText().replace('[', '\0').replace(']', '\0'); //Remove the initial @ diff --git a/src/test/java/emailvalidator4j/EmailValidatorTest.java b/src/test/java/emailvalidator4j/EmailValidatorTest.java index ff5022e..73480df 100644 --- a/src/test/java/emailvalidator4j/EmailValidatorTest.java +++ b/src/test/java/emailvalidator4j/EmailValidatorTest.java @@ -57,6 +57,9 @@ public static Object[][] invalidEmailProvider() { {"comment(example))@example.com"}, {"example@example)comment.com"}, {"example@example(comment)).com"}, + {"example@[1.2.3.4"}, + {"example@[IPv6:1:2:3:4:5:6:7:8"}, + {"exam(ple@exam).ple"}, {"example@(example))comment.com"} }; From d5758b0f5ce0c0a06cb63191e23d1dfb304d2d55 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Wed, 17 Jul 2019 12:03:10 +0200 Subject: [PATCH 3/6] fix travis issues with xenial dist --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c4f11b7..926179f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +dist: trusty language: java jdk: - - oraclejdk8 \ No newline at end of file + - oraclejdk8 + - openjdk8 From 6273e3400f57089c881a6e76f960e23b47bfe180 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Wed, 17 Jul 2019 12:04:27 +0200 Subject: [PATCH 4/6] Fix #13 - String lenght causing overflow on regex matching --- build.gradle | 1 + src/main/java/emailvalidator4j/lexer/EmailLexer.java | 5 ++++- src/main/java/emailvalidator4j/parser/DomainPart.java | 2 +- src/main/java/emailvalidator4j/parser/Email.java | 9 +++++++++ src/main/java/emailvalidator4j/parser/LocalPart.java | 2 +- src/test/java/emailvalidator4j/EmailValidatorTest.java | 8 ++++++++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index df3966c..6bb38d6 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' testCompile group: 'com.tngtech.java', name: 'junit-dataprovider', version: '1.9.2' testCompile "org.mockito:mockito-core:1.+" + testCompile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0' } def siteUrl = 'https://github.com/egulias/EmailValidator4J' diff --git a/src/main/java/emailvalidator4j/lexer/EmailLexer.java b/src/main/java/emailvalidator4j/lexer/EmailLexer.java index 7d56eb3..a059f21 100644 --- a/src/main/java/emailvalidator4j/lexer/EmailLexer.java +++ b/src/main/java/emailvalidator4j/lexer/EmailLexer.java @@ -1,5 +1,6 @@ package emailvalidator4j.lexer; +import com.sun.javaws.exceptions.InvalidArgumentException; import emailvalidator4j.lexer.exception.TokenNotFound; import java.util.ArrayList; import java.util.List; @@ -16,8 +17,10 @@ public class EmailLexer { public void lex(String input) { Pattern pattern = Pattern.compile( - "(([a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~]|[^\\u0000-\\u007F])+[46]?)|([0-9]+)|(\r\n)|(::)|(\\s+?)|(.)|(\\p{Cc}+)", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE + "(([a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~]|[^\\u0000-\\u007F])+[46]?)|([0-9]+)|(\r\n)|(::)|(\\s+?)|(.)|(\\p{Cc}+)", + Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE ); + Matcher matcher = pattern.matcher(input); this.reset(); diff --git a/src/main/java/emailvalidator4j/parser/DomainPart.java b/src/main/java/emailvalidator4j/parser/DomainPart.java index b069f19..6d35f9a 100755 --- a/src/main/java/emailvalidator4j/parser/DomainPart.java +++ b/src/main/java/emailvalidator4j/parser/DomainPart.java @@ -13,8 +13,8 @@ final class DomainPart extends Parser { private static final Pattern subDomainIllegalCharacters = Pattern.compile("[^a-zA-Z0-9\\-\\x00007F-\\u10FFFF]"); - private static final int DOMAINPART_MAX_LENGTH = 255; private static final int LABEL_MAX_LENGTH = 63; + public static final int DOMAINPART_MAX_LENGTH = 255; private final HashSet notAllowedTokens = new HashSet(2) {{ add(Tokens.BACKSLASH); add(Tokens.SLASH); diff --git a/src/main/java/emailvalidator4j/parser/Email.java b/src/main/java/emailvalidator4j/parser/Email.java index 4f70c30..6ffae8c 100644 --- a/src/main/java/emailvalidator4j/parser/Email.java +++ b/src/main/java/emailvalidator4j/parser/Email.java @@ -24,6 +24,8 @@ public Email(EmailLexer lexer) { } public void parse(String email) throws InvalidEmail { + this.validateLength(email); + this.lexer.lex(Optional.ofNullable(email).orElseThrow(() -> new InvalidEmail("Empty email") )); @@ -40,6 +42,13 @@ public void parse(String email) throws InvalidEmail { this.domainPartParser.parse(this.lexer.toString()); } + private void validateLength(String email) throws InvalidEmail { + int maxLength = LocalPart.RFC5321_LOCALPART_MAX_LENGTH + DomainPart.DOMAINPART_MAX_LENGTH + 1; + if (email.length() > maxLength) { + throw new InvalidEmail("email too long"); + } + } + public List getWarnings() { List warnings = this.localPartParser.getWarnings(); warnings.addAll(this.domainPartParser.getWarnings()); diff --git a/src/main/java/emailvalidator4j/parser/LocalPart.java b/src/main/java/emailvalidator4j/parser/LocalPart.java index 8bf4ee2..4dd50e7 100644 --- a/src/main/java/emailvalidator4j/parser/LocalPart.java +++ b/src/main/java/emailvalidator4j/parser/LocalPart.java @@ -13,7 +13,7 @@ final class LocalPart extends Parser { private boolean closingQuote = false; private boolean parseDQuote = true; - private static int RFC5321_LOCALPART_MAX_LENGTH = 64; + public static int RFC5321_LOCALPART_MAX_LENGTH = 64; LocalPart (EmailLexer lexer) { super(lexer); diff --git a/src/test/java/emailvalidator4j/EmailValidatorTest.java b/src/test/java/emailvalidator4j/EmailValidatorTest.java index 73480df..d101559 100644 --- a/src/test/java/emailvalidator4j/EmailValidatorTest.java +++ b/src/test/java/emailvalidator4j/EmailValidatorTest.java @@ -3,6 +3,7 @@ import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -134,4 +135,11 @@ public void warningsAreExposed() { validator.isValid("test@[127.0.0.0]"); Assert.assertFalse(validator.getWarnings().isEmpty()); } + + @Test + public void controlStringOverflow() { + String filled = StringUtils.repeat("a", 2000); + EmailValidator validator = new EmailValidator(); + Assert.assertFalse(validator.isValid(filled.concat("@example.com"))); + } } From 60833b31872d72dc8414f1bafac3e3d89a9dcf5a Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Wed, 17 Jul 2019 12:18:30 +0200 Subject: [PATCH 5/6] Remove unused package --- src/main/java/emailvalidator4j/lexer/EmailLexer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/emailvalidator4j/lexer/EmailLexer.java b/src/main/java/emailvalidator4j/lexer/EmailLexer.java index a059f21..f743628 100644 --- a/src/main/java/emailvalidator4j/lexer/EmailLexer.java +++ b/src/main/java/emailvalidator4j/lexer/EmailLexer.java @@ -1,6 +1,5 @@ package emailvalidator4j.lexer; -import com.sun.javaws.exceptions.InvalidArgumentException; import emailvalidator4j.lexer.exception.TokenNotFound; import java.util.ArrayList; import java.util.List; From e67e04e9ae0490ee390900ce96f6e106ca12240e Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Thu, 18 Jul 2019 23:07:47 +0200 Subject: [PATCH 6/6] Prevent null string for email --- src/main/java/emailvalidator4j/parser/Email.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/emailvalidator4j/parser/Email.java b/src/main/java/emailvalidator4j/parser/Email.java index 6ffae8c..5054458 100644 --- a/src/main/java/emailvalidator4j/parser/Email.java +++ b/src/main/java/emailvalidator4j/parser/Email.java @@ -24,11 +24,12 @@ public Email(EmailLexer lexer) { } public void parse(String email) throws InvalidEmail { - this.validateLength(email); - this.lexer.lex(Optional.ofNullable(email).orElseThrow(() -> - new InvalidEmail("Empty email") - )); + String nonEmptyEmail = Optional.ofNullable(email).orElseThrow(() -> + new InvalidEmail("Empty email")); + this.validateLength(nonEmptyEmail); + + this.lexer.lex(nonEmptyEmail); if (!this.lexer.find(Tokens.AT)) { throw new NoLocalPart("No local part found"); @@ -44,6 +45,7 @@ public void parse(String email) throws InvalidEmail { private void validateLength(String email) throws InvalidEmail { int maxLength = LocalPart.RFC5321_LOCALPART_MAX_LENGTH + DomainPart.DOMAINPART_MAX_LENGTH + 1; + if (email.length() > maxLength) { throw new InvalidEmail("email too long"); }