diff --git a/arguments.go b/arguments.go index e36595d..22f67be 100644 --- a/arguments.go +++ b/arguments.go @@ -268,6 +268,12 @@ func expandInputMacroExt(content string, totalLen *int) ([]string, error) { if name == "" { return nil, ErrInputMacroEmptyKey } + // A name that still ends in a repeat suffix (e.g. "{a*1*2}" leaves "a*1") + // cannot be written back as "{name}": re-reading would strip the suffix a + // second time and yield a different macro. Reject the ambiguous form. + if stripped, _, stripErr := parseSuffixRepeat(name); stripErr != nil || stripped != name { + return nil, ErrInputMacroAmbiguousKey + } // Single-rune keys are appended without braces (e.g. "a", "*"). // Multi-rune names need braces so ParseKeyCombo recognises them. diff --git a/parser_input_macro_test.go b/parser_input_macro_test.go index b5b0161..a06dea0 100644 --- a/parser_input_macro_test.go +++ b/parser_input_macro_test.go @@ -122,6 +122,16 @@ func TestInputMacroGrammar(t *testing.T) { input: "**input.keyboard:{a*b}", want: kbd("{a*b}"), }, + { + name: "trailing asterisk in combo is literal", + input: "**input.keyboard:{ctrl+*}", + want: kbd("{ctrl+*}"), + }, + { + name: "asterisk before zero is literal", + input: "**input.keyboard:{a*0}", + want: kbd("{a*0}"), + }, { name: "repeat in mixed sequence", input: "**input.keyboard:a{enter*2}b", @@ -347,6 +357,16 @@ func TestInputMacroCaps(t *testing.T) { input: "**input.keyboard:{*5}", wantErr: zapscript.ErrInputMacroEmptyKey, }, + { + name: "key name left with a repeat suffix", + input: "**input.keyboard:{a*1*2}", + wantErr: zapscript.ErrInputMacroAmbiguousKey, + }, + { + name: "repeat suffix only key name", + input: "**input.keyboard:{*1*1}", + wantErr: zapscript.ErrInputMacroAmbiguousKey, + }, { name: "unclosed quoted literal at EOF", input: `**input.keyboard:{"unclosed`, diff --git a/symbols.go b/symbols.go index e844222..6f2af1c 100644 --- a/symbols.go +++ b/symbols.go @@ -38,6 +38,7 @@ var ( ErrInputMacroRepeatTooLarge = errors.New("input macro repeat count exceeds maximum") ErrInputMacroTooLong = errors.New("input macro expanded key count exceeds maximum") ErrInputMacroEmptyKey = errors.New("input macro key name is empty after repeat suffix removal") + ErrInputMacroAmbiguousKey = errors.New("input macro key name ends in a repeat suffix") ) const ( diff --git a/testdata/fuzz/FuzzCommandString/8b2c3a3ac03788e5 b/testdata/fuzz/FuzzCommandString/8b2c3a3ac03788e5 new file mode 100644 index 0000000..bea0d20 --- /dev/null +++ b/testdata/fuzz/FuzzCommandString/8b2c3a3ac03788e5 @@ -0,0 +1,2 @@ +go test fuzz v1 +string("**input.keYBoArd:{*1*1}")