Skip to content

Commit c37b79e

Browse files
author
Francesc Campoy
committed
Improve regex error messages to surface pattern in output
Wrap regexp compile errors to include the full pattern string, making it easy to identify which directive failed and audit patterns in PR reviews. Update existing tests and add new cases covering the improved error format, missing-slashes validation, and a valid-pattern regression. Add a security note to the package godoc. Closes #83
1 parent 870991f commit c37b79e

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

embedmd/embedmd.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@
4949
// go, this will fail with other files like .md whose language name is markdown.
5050
//
5151
// [embedmd]:# (file.ext)
52+
//
53+
// Security note: embed directives, including their regular expression patterns,
54+
// are treated as trusted input. Markdown files containing embedmd directives
55+
// should not be sourced from untrusted contributors without careful review, as
56+
// a crafted regular expression could match unintended content from the embedded
57+
// file.
5258
package embedmd
5359

5460
import (
@@ -122,7 +128,7 @@ func extract(b []byte, start, end *string) ([]byte, error) {
122128
}
123129
re, err := regexp.CompilePOSIX(s[1 : len(s)-1])
124130
if err != nil {
125-
return nil, err
131+
return nil, fmt.Errorf("invalid regexp %s: %v", s, err)
126132
}
127133
loc := re.FindIndex(b)
128134
if loc == nil {

embedmd/embedmd_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,24 @@ func TestExtract(t *testing.T) {
6262
start: testutil.Ptr("/func main/"), end: testutil.Ptr("/}/"), out: "func main() {\n fmt.Println(\"hello, test\")\n}"},
6363

6464
{name: "bad start regexp",
65-
start: testutil.Ptr("/(/"), err: "error parsing regexp: missing closing ): `(`"},
65+
start: testutil.Ptr("/(/"), err: "invalid regexp /(/: error parsing regexp: missing closing ): `(`"},
6666
{name: "bad regexp",
6767
start: testutil.Ptr("something"), err: "missing slashes (/) around \"something\""},
6868
{name: "bad end regexp",
69-
start: testutil.Ptr("/fmt.P/"), end: testutil.Ptr("/)/"), err: "error parsing regexp: unexpected ): `)`"},
69+
start: testutil.Ptr("/fmt.P/"), end: testutil.Ptr("/)/"), err: "invalid regexp /)/: error parsing regexp: unexpected ): `)`"},
7070

7171
{name: "start and end of line ^$",
7272
start: testutil.Ptr("/^func main/"), end: testutil.Ptr("/}$/"), out: "func main() {\n fmt.Println(\"hello, test\")\n}"},
73+
74+
// Error message quality: invalid patterns should include the pattern string.
75+
{name: "invalid regexp shows pattern in error",
76+
start: testutil.Ptr("/[invalid/"), err: "invalid regexp /[invalid/: error parsing regexp: missing closing ]: `[invalid`"},
77+
// Missing slashes should report the raw value.
78+
{name: "missing slashes reports value",
79+
start: testutil.Ptr("noSlashes"), err: "missing slashes (/) around \"noSlashes\""},
80+
// Valid pattern regression: correctly matches a simple pattern.
81+
{name: "valid pattern still works",
82+
start: testutil.Ptr("/fmt\\.Println/"), out: "fmt.Println"},
7383
}
7484

7585
for _, tt := range tc {

0 commit comments

Comments
 (0)