badoux / checkmail

Golang package for email validation
MIT License
710 stars 92 forks source link

runtime error: slice bounds out of range [:-1] #34

Closed ghost closed 3 years ago

ghost commented 3 years ago

split() fails if the email address passed through is blank and returns runtime error: slice bounds out of range [:-1]

For example using ValidateHost() and passing an empty string or does not contain @ symbol

var formData struct {
    EmailAddress string
    ...
}
// get form data from post and populate formData variable

// assume formData.EmailAddress = "" or does not contain @ symbol
err := checkmail.ValidateHost(formData.EmailAddress)
if err != nil {
    fmt.Println(err)
}

This would happen where ever split() is used

func split(email string) (account, host string, err error) {
        // This is where the code currently fails as email = "" or does not contain the @ symbol
    i := strings.LastIndexByte(email, '@')
    account = email[:i]
    host = email[i+1:]
    return
}

Below is an updated split() function I have tested which could be a solution?

It reuses the regex used by ValidateFormat() before trying to generate the slice and passes the error back and allows for it to be caught by the error returned by checkmail.ValidateHost(...)

func split(email string) (account, host string, err error) {
    if !emailRegexp.MatchString(strings.ToLower(email)) {
        err = ErrBadFormat
        return
    }
    i := strings.LastIndexByte(email, '@')
    account = email[:i]
    host = email[i+1:]
    return
}

This feels a bit more robust compared to checking the format and then checking if the user/host is valid? Correct me if I'm wrong

Another potential solution could be the below if you don't want to use the regex again? and just checks that the email being passed in is not an empty string and contains the @ symbol

func split(email string) (account, host string, err error) {
    if email == "" || !strings.Contains(email, "@") {
        err = ErrBadFormat
        return
    }
    fmt.Println("Getting LastIndexByte")
    i := strings.LastIndexByte(email, '@')
    account = email[:i]
    fmt.Println(account)
    host = email[i+1:]
    fmt.Println(host)
    return
}
ghost commented 3 years ago

36 Add check in split utility method to prevent panic - This issue will be fixed with introduction of checking in this pull request