Shouldn't rewrite dot in a string to index syntax (#502)

Co-authored-by: Casey Lee <cplee@nektos.com>
This commit is contained in:
KADOTA, Kyohei 2021-02-09 02:14:12 +09:00 committed by GitHub
parent fc46f506e3
commit 316b078f8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 12 deletions

View file

@ -16,10 +16,9 @@ import (
"gopkg.in/godo.v2/glob"
)
var contextPattern, expressionPattern, operatorPattern *regexp.Regexp
var expressionPattern, operatorPattern *regexp.Regexp
func init() {
contextPattern = regexp.MustCompile(`^([^.]*(?:\[.+])*)(?:\.([\w-]+))?(.*)$`)
expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
operatorPattern = regexp.MustCompile("^[!=><|&]+$")
}
@ -123,22 +122,88 @@ func (ee *expressionEvaluator) InterpolateWithStringCheck(in string) (string, bo
// Rewrite tries to transform any javascript property accessor into its bracket notation.
// For instance, "object.property" would become "object['property']".
func (ee *expressionEvaluator) Rewrite(in string) string {
re := in
var buf strings.Builder
r := strings.NewReader(in)
for {
matches := contextPattern.FindStringSubmatch(re)
if matches == nil {
// No global match, we're done!
c, _, err := r.ReadRune()
if err == io.EOF {
break
}
if matches[2] == "" {
// No property match, we're done!
break
//nolint
switch {
default:
buf.WriteRune(c)
case c == '\'':
buf.WriteRune(c)
ee.advString(&buf, r)
case c == '.':
buf.WriteString("['")
ee.advPropertyName(&buf, r)
buf.WriteString("']")
}
re = fmt.Sprintf("%s['%s']%s", matches[1], matches[2], matches[3])
}
return buf.String()
}
return re
func (*expressionEvaluator) advString(w *strings.Builder, r *strings.Reader) error {
for {
c, _, err := r.ReadRune()
if err != nil {
return err
}
if c != '\'' {
w.WriteRune(c) //nolint
continue
}
// Handles a escaped string: ex. 'It''s ok'
c, _, err = r.ReadRune()
if err != nil {
w.WriteString("'") //nolint
return err
}
if c != '\'' {
w.WriteString("'") //nolint
if err := r.UnreadRune(); err != nil {
return err
}
break
}
w.WriteString(`\'`) //nolint
}
return nil
}
func (*expressionEvaluator) advPropertyName(w *strings.Builder, r *strings.Reader) error {
for {
c, _, err := r.ReadRune()
if err != nil {
return err
}
if !isLetter(c) {
if err := r.UnreadRune(); err != nil {
return err
}
break
}
w.WriteRune(c) //nolint
}
return nil
}
func isLetter(c rune) bool {
switch {
case c >= 'a' && c <= 'z':
return true
case c >= 'A' && c <= 'Z':
return true
case c >= '0' && c <= '9':
return true
case c == '_' || c == '-':
return true
default:
return false
}
}
func (rc *RunContext) newVM() *otto.Otto {

View file

@ -89,6 +89,8 @@ func TestEvaluate(t *testing.T) {
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar", ""},
{"hashFiles('**/non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
{"hashFiles('**/non-extant-files', '**/more-non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
{"hashFiles('**/non.extant.files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
{"hashFiles('**/non''extant''files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
{"success()", "true", ""},
{"failure()", "false", ""},
{"always()", "true", ""},