Skip to content

Commit

Permalink
fix: handle additional broken macro definitions (#1180)
Browse files Browse the repository at this point in the history
Signed-off-by: Felipe Zipitria <felipe.zipitria@owasp.org>
  • Loading branch information
fzipi authored Oct 28, 2024
1 parent 0b0ada4 commit abf359e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
29 changes: 16 additions & 13 deletions experimental/plugins/macro/macro.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,38 +99,38 @@ func (m *macro) compile(input string) error {
return fmt.Errorf("empty macro")
}

currentToken := strings.Builder{}
m.original = input
var currentToken strings.Builder
isMacro := false

for i := 0; i < l; i++ {
c := input[i]
if c == '%' && (i <= l && input[i+1] == '{') {
// we have a macro

if c == '%' && i+1 < l && input[i+1] == '{' {
if currentToken.Len() > 0 {
// we add the text token
m.tokens = append(m.tokens, macroToken{
text: currentToken.String(),
variable: variables.Unknown,
key: "",
})
currentToken.Reset()
}
currentToken.Reset()
isMacro = true
i++
i++ // Skip '{'
continue
}

if isMacro {
if c == '}' {
// we close a macro
isMacro = false
// TODO(jcchavezs): key should only be empty in single collections
if input[i-1] == '.' {
return fmt.Errorf("empty variable name")
}
varName, key, _ := strings.Cut(currentToken.String(), ".")
v, err := variables.Parse(varName)
if err != nil {
return fmt.Errorf("unknown variable %q", varName)
}
// we add the variable token
m.tokens = append(m.tokens, macroToken{
text: currentToken.String(),
variable: v,
Expand All @@ -140,8 +140,7 @@ func (m *macro) compile(input string) error {
continue
}

if !(c == '.' || c == '_' || c == '-' || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
currentToken.WriteByte(c)
if !isValidMacroChar(c) {
return fmt.Errorf("malformed variable starting with %q", "%{"+currentToken.String())
}

Expand All @@ -152,10 +151,10 @@ func (m *macro) compile(input string) error {
}
continue
}
// we have a normal character

currentToken.WriteByte(c)
}
// if there is something left

if currentToken.Len() > 0 {
m.tokens = append(m.tokens, macroToken{
text: currentToken.String(),
Expand All @@ -166,6 +165,10 @@ func (m *macro) compile(input string) error {
return nil
}

func isValidMacroChar(c byte) bool {
return c == '.' || c == '_' || c == '-' || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
}

// String returns the original string
func (m *macro) String() string {
return m.original
Expand Down
34 changes: 33 additions & 1 deletion experimental/plugins/macro/macro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,39 @@ func TestCompile(t *testing.T) {
}
})

t.Run("malformed macro", func(t *testing.T) {
t.Run("single percent sign", func(t *testing.T) {
m := &macro{}
err := m.compile("%")
if err != nil {
t.Errorf("single percent sign should not error")
}
})

t.Run("empty braces", func(t *testing.T) {
m := &macro{}
err := m.compile("%{}")
if err == nil {
t.Errorf("expected error for empty braces")
}
})

t.Run("missing key", func(t *testing.T) {
m := &macro{}
err := m.compile("%{tx.}")
if err == nil {
t.Errorf("expected error for missing key")
}
})

t.Run("missing collection", func(t *testing.T) {
m := &macro{}
err := m.compile("%{.key}")
if err == nil {
t.Errorf("expected error for missing collection")
}
})

t.Run("malformed macros", func(t *testing.T) {
for _, test := range []string{"%{tx.count", "%{{tx.count}", "%{{tx.{count}", "something %{tx.count"} {
t.Run(test, func(t *testing.T) {
m := &macro{}
Expand Down

0 comments on commit abf359e

Please sign in to comment.