Skip to content

Commit 68aea8c

Browse files
authored
fix(security): escape generated table-name Go string literal (#84)
1 parent 9c53736 commit 68aea8c

2 files changed

Lines changed: 50 additions & 19 deletions

File tree

generator.go

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"go/format"
88
"os"
99
"path/filepath"
10+
"strconv"
1011
"strings"
1112
"text/template"
1213

@@ -26,15 +27,16 @@ type GenerateOptions struct {
2627
}
2728

2829
type templateData struct {
29-
Imports string
30-
Model string
31-
ModelLower string
32-
M string
33-
Package string
34-
Fields string
35-
UpdaterFields string
36-
ScannedFields string
37-
TableName string
30+
Imports string
31+
Model string
32+
ModelLower string
33+
M string
34+
Package string
35+
Fields string
36+
UpdaterFields string
37+
ScannedFields string
38+
TableName string
39+
TableNameGoLiteral string
3840
}
3941

4042
func NewGenerator(db *sql.DB) Generator {
@@ -120,15 +122,16 @@ func (d *generator) generateModelFile(tableName string, opt *GenerateOptions) er
120122
}
121123
}
122124
data := &templateData{
123-
Imports: strings.Join(imports, "\n"),
124-
Model: strcase.ToCamel(table.TableName),
125-
ModelLower: strcase.ToLowerCamel(table.TableName),
126-
M: table.TableName[0:1],
127-
UpdaterFields: updateFields.String(),
128-
Package: opt.Package,
129-
Fields: fields.String(),
130-
TableName: tableName,
131-
ScannedFields: scannedFields.String(),
125+
Imports: strings.Join(imports, "\n"),
126+
Model: strcase.ToCamel(table.TableName),
127+
ModelLower: strcase.ToLowerCamel(table.TableName),
128+
M: table.TableName[0:1],
129+
UpdaterFields: updateFields.String(),
130+
Package: opt.Package,
131+
Fields: fields.String(),
132+
TableName: tableName,
133+
TableNameGoLiteral: strconv.Quote(tableName),
134+
ScannedFields: scannedFields.String(),
132135
}
133136
outFile := filepath.Join(
134137
opt.OutDir,
@@ -167,5 +170,5 @@ func ({{.M}} *Update{{.Model}}) UpdateTableName() string {
167170
return {{.Model}}TableName
168171
}
169172
170-
const {{.Model}}TableName = "{{.TableName}}"
173+
const {{.Model}}TableName = {{.TableNameGoLiteral}}
171174
`

generator_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"regexp"
78
"testing"
89

910
"github.com/DATA-DOG/go-sqlmock"
@@ -108,3 +109,30 @@ func TestGenerator_Generate(t *testing.T) {
108109
}), "columns err")
109110
})
110111
}
112+
113+
func TestGenerator_Generate_EscapesTableNameGoLiteral(t *testing.T) {
114+
mockDb, mock, err := sqlmock.New()
115+
assert.NoError(t, err)
116+
defer mockDb.Close()
117+
118+
table := `x";func init(){panic(1)};var _="`
119+
mock.ExpectQuery(`show tables`).WillReturnRows(sqlmock.NewRows([]string{"tables"}).AddRow(table))
120+
mock.ExpectQuery(regexp.QuoteMeta(fmt.Sprintf("show columns from `%s`", table))).WillReturnRows(
121+
sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}).
122+
AddRow("id", "int(11)", "NO", "PRI", nil, ""),
123+
)
124+
125+
dir := t.TempDir()
126+
err = NewGenerator(mockDb).Generate(&GenerateOptions{OutDir: dir, Package: "dist"})
127+
assert.NoError(t, err)
128+
129+
entries, err := os.ReadDir(dir)
130+
assert.NoError(t, err)
131+
if assert.Len(t, entries, 1) {
132+
content, err := os.ReadFile(filepath.Join(dir, entries[0].Name()))
133+
assert.NoError(t, err)
134+
assert.Contains(t, string(content), `const XfuncInitpanic1varTableName = "x\";func init(){panic(1)};var _=\""`)
135+
assert.NotContains(t, string(content), "\nfunc init()")
136+
}
137+
assert.NoError(t, mock.ExpectationsWereMet())
138+
}

0 commit comments

Comments
 (0)