Skip to content

Commit 22ba94a

Browse files
authored
Merge pull request #7 from tttoad/fix-parse-panic
Fix: panic during tags processing
2 parents 9e1a95f + cc14d3c commit 22ba94a

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

tagalign.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ const (
2929
StrictStyle
3030
)
3131

32+
const (
33+
errTagValueSyntax = "bad syntax for struct tag value"
34+
)
35+
3236
func NewAnalyzer(options ...Option) *analysis.Analyzer {
3337
return &analysis.Analyzer{
3438
Name: "tagalign",
@@ -208,16 +212,25 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit
208212
uniqueKeys = append(uniqueKeys, k)
209213
}
210214

211-
for i, field := range fields {
212-
offsets[i] = pass.Fset.Position(field.Tag.Pos()).Column
215+
for i := 0; i < len(fields); {
216+
field := fields[i]
217+
column := pass.Fset.Position(field.Tag.Pos()).Column - 1
218+
offsets[i] = column
219+
213220
tag, err := strconv.Unquote(field.Tag.Value)
214221
if err != nil {
215-
break
222+
// if tag value is not a valid string, report it directly
223+
w.report(pass, field, column, errTagValueSyntax, field.Tag.Value)
224+
fields = removeField(fields, i)
225+
continue
216226
}
217227

218228
tags, err := structtag.Parse(tag)
219229
if err != nil {
220-
break
230+
// if tag value is not a valid struct tag, report it directly
231+
w.report(pass, field, column, err.Error(), field.Tag.Value)
232+
fields = removeField(fields, i)
233+
continue
221234
}
222235

223236
maxTagNum = max(maxTagNum, tags.Len())
@@ -234,6 +247,8 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit
234247
addKey(t.Key)
235248
}
236249
tagsGroup = append(tagsGroup, tags.Tags())
250+
251+
i++
237252
}
238253

239254
if w.sort && StrictStyle == w.style {
@@ -325,19 +340,22 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit
325340

326341
msg := "tag is not aligned, should be: " + unquoteTag
327342

328-
w.report(pass, field, offsets[i]-1, msg, newTagValue)
343+
w.report(pass, field, offsets[i], msg, newTagValue)
329344
}
330345
}
331346

332347
// process single fields
333348
for _, field := range w.singleFields {
349+
column := pass.Fset.Position(field.Tag.Pos()).Column - 1
334350
tag, err := strconv.Unquote(field.Tag.Value)
335351
if err != nil {
352+
w.report(pass, field, column, errTagValueSyntax, field.Tag.Value)
336353
continue
337354
}
338355

339356
tags, err := structtag.Parse(tag)
340357
if err != nil {
358+
w.report(pass, field, column, err.Error(), field.Tag.Value)
341359
continue
342360
}
343361
originalTags := append([]*structtag.Tag(nil), tags.Tags()...)
@@ -353,7 +371,7 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit
353371

354372
msg := "tag is not aligned , should be: " + tags.String()
355373

356-
w.report(pass, field, pass.Fset.Position(field.Tag.Pos()).Column-1, msg, newTagValue)
374+
w.report(pass, field, column, msg, newTagValue)
357375
}
358376
}
359377

@@ -431,3 +449,11 @@ func max(a, b int) int {
431449
}
432450
return b
433451
}
452+
453+
func removeField(fields []*ast.Field, index int) []*ast.Field {
454+
if index < 0 || index >= len(fields) {
455+
return fields
456+
}
457+
458+
return append(fields[:index], fields[index+1:]...)
459+
}

tagalign_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func Test_alignAndSortWithOrder(t *testing.T) {
3939
assert.NoError(t, err)
4040
analysistest.Run(t, sort, a)
4141
}
42+
4243
func TestSprintf(t *testing.T) {
4344
format := alignFormat(20)
4445
assert.Equal(t, "%-20s", format)
@@ -72,3 +73,11 @@ func Test_alignSingleField(t *testing.T) {
7273
assert.NoError(t, err)
7374
analysistest.Run(t, unsort, a)
7475
}
76+
77+
func Test_badSyntaxTag(t *testing.T) {
78+
// only align
79+
a := NewAnalyzer()
80+
unsort, err := filepath.Abs("testdata/bad_syntax_tag")
81+
assert.NoError(t, err)
82+
analysistest.Run(t, unsort, a)
83+
}

testdata/bad_syntax_tag/example.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package issues6
2+
3+
type FooBar struct {
4+
Foo int `json: "foo" validate:"required"` // want `bad syntax for struct tag value`
5+
Bar string `json:bar` // want `bad syntax for struct tag value`
6+
FooFoo int8 `json:"foo_foo" validate:"required"`
7+
BarBar int `json:"bar_bar" validate:"required"`
8+
}
9+
10+
type FooBar2 struct {
11+
Foo int `json:"foo" validate:"required"`
12+
13+
FooFoo int8 `json:"foo_foo"`
14+
BarBar int `json:"bar_bar" validate:"required"`
15+
XXX int `json:"xxx" validate:"required"`
16+
Bar string `json:bar` // want `bad syntax for struct tag value`
17+
}

0 commit comments

Comments
 (0)