mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-27 17:23:00 +00:00
Bot: Fixed trailing backticks causing out of bound panic
This commit is contained in:
parent
5acf9f3f22
commit
64ab8c4f30
|
@ -5,18 +5,45 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WordOffset is the offset from the position cursor to print on the error.
|
||||||
|
const WordOffset = 7
|
||||||
|
|
||||||
|
var escaper = strings.NewReplacer(
|
||||||
|
"`", "\\`",
|
||||||
|
"@", "\\@",
|
||||||
|
"\\", "\\\\",
|
||||||
|
)
|
||||||
|
|
||||||
type ErrParse struct {
|
type ErrParse struct {
|
||||||
Position int
|
Position int
|
||||||
ErrorStart,
|
Words string // joined
|
||||||
ErrorPart,
|
|
||||||
ErrorEnd string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ErrParse) Error() string {
|
func (e ErrParse) Error() string {
|
||||||
return fmt.Sprintf(
|
// Magic number 5.
|
||||||
"Unexpected quote or escape: %s__%s__%s",
|
var a = max(0, e.Position-WordOffset)
|
||||||
e.ErrorStart, e.ErrorPart, e.ErrorEnd,
|
var b = min(len(e.Words), e.Position+WordOffset)
|
||||||
|
var word = e.Words[a:b]
|
||||||
|
var uidx = e.Position - a
|
||||||
|
|
||||||
|
errstr := strings.Builder{}
|
||||||
|
errstr.WriteString("Unexpected quote or escape")
|
||||||
|
|
||||||
|
// Do a bound check.
|
||||||
|
if uidx+1 > len(word) {
|
||||||
|
// Invalid.
|
||||||
|
errstr.WriteString(".")
|
||||||
|
return errstr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the pre-underline part.
|
||||||
|
fmt.Fprintf(
|
||||||
|
&errstr, ": %s__%s__",
|
||||||
|
escaper.Replace(word[:uidx]),
|
||||||
|
escaper.Replace(string(word[uidx:])),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return errstr.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses the given text to a slice of words.
|
// Parse parses the given text to a slice of words.
|
||||||
|
@ -76,11 +103,6 @@ func Parse(line string) ([]string, error) {
|
||||||
got = true
|
got = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// // If this is a backtick, then write it.
|
|
||||||
// if r == '`' {
|
|
||||||
// buf.WriteByte('`')
|
|
||||||
// }
|
|
||||||
|
|
||||||
singleQuoted = !singleQuoted
|
singleQuoted = !singleQuoted
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -95,19 +117,9 @@ func Parse(line string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if escaped || singleQuoted || doubleQuoted {
|
if escaped || singleQuoted || doubleQuoted {
|
||||||
// the number of characters to highlight
|
|
||||||
var (
|
|
||||||
pos = cursor + 5
|
|
||||||
start = string(runes[max(cursor-100, 0) : pos-1])
|
|
||||||
end = string(runes[pos+1 : min(cursor+100, len(runes))])
|
|
||||||
part = string(runes[max(pos-1, 0):min(len(runes), pos+2)])
|
|
||||||
)
|
|
||||||
|
|
||||||
return args, &ErrParse{
|
return args, &ErrParse{
|
||||||
Position: cursor,
|
Position: cursor + buf.Len(),
|
||||||
ErrorStart: start,
|
Words: strings.Join(args, " "),
|
||||||
ErrorPart: part,
|
|
||||||
ErrorEnd: end,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,16 @@ func TestParse(t *testing.T) {
|
||||||
[]string{"how", "about", "a", "go\npackage main\n", "go", "code?"},
|
[]string{"how", "about", "a", "go\npackage main\n", "go", "code?"},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"this should not crash `",
|
||||||
|
[]string{"this", "should", "not", "crash"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"this should not crash '",
|
||||||
|
[]string{"this", "should", "not", "crash"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in a new issue