Skip to content

Commit b03a2bc

Browse files
Resolve conflicts with main
2 parents 7b9ca38 + e9ce36a commit b03a2bc

File tree

5 files changed

+229
-23
lines changed

5 files changed

+229
-23
lines changed

tests/passed-tests.txt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,15 @@ TestNilPointerSlice
212212
TestNilPointerSlice2
213213
TestPrefixedPreloadDuplication
214214
TestPreloadManyToManyCallbacks
215-
#TestPreloadWithAssociations
216-
#TestNestedPreload
215+
TestPreloadWithAssociations
216+
TestNestedPreload
217217
TestNestedPreloadForSlice
218218
#TestPreloadWithConds
219-
#TestNestedPreloadWithConds
219+
TestNestedPreloadWithConds
220220
TestPreloadEmptyData
221221
TestPreloadGoroutine
222-
#TestPreloadWithDiffModel
223-
#TestNestedPreloadWithUnscoped
222+
TestPreloadWithDiffModel
223+
TestNestedPreloadWithUnscoped
224224
TestNestedPreloadWithNestedJoin
225225
#TestMergeNestedPreloadWithNestedJoin
226226
TestNestedPreloadWithPointerJoin
@@ -370,7 +370,7 @@ TestDistinctWithVaryingCase
370370
#TestDistinctWithAggregation
371371
TestUpsertWithSave
372372
TestFindOrInitialize
373-
#TestFindOrCreate
373+
TestFindOrCreate
374374
TestUpdateWithMissWhere
375375
BenchmarkCreate
376376
BenchmarkFind
@@ -379,4 +379,8 @@ BenchmarkScanSlice
379379
BenchmarkScanSlicePointer
380380
BenchmarkUpdate
381381
BenchmarkDelete
382+
TestRawQueryInjection
383+
TestWhereClauseInjection
384+
TestUpdateInjection
385+
TestFirstOrCreateInjection
382386
TesUserInsertScenarios

tests/preload_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func TestPreloadWithAssociations(t *testing.T) {
7676
CheckUser(t, user, user)
7777

7878
var user2 User
79-
DB.Preload(clause.Associations).Find(&user2, "id = ?", user.ID)
79+
DB.Preload(clause.Associations).Find(&user2, "\"id\" = ?", user.ID)
8080
CheckUser(t, user2, user)
8181

8282
user3 := *GetUser("preload_with_associations_new", Config{
@@ -90,7 +90,7 @@ func TestPreloadWithAssociations(t *testing.T) {
9090
Friends: 1,
9191
})
9292

93-
DB.Preload(clause.Associations).Find(&user3, "id = ?", user.ID)
93+
DB.Preload(clause.Associations).Find(&user3, "\"id\" = ?", user.ID)
9494
CheckUser(t, user3, user)
9595
}
9696

@@ -107,15 +107,15 @@ func TestNestedPreload(t *testing.T) {
107107
}
108108

109109
var user2 User
110-
DB.Preload("Pets.Toy").Find(&user2, "id = ?", user.ID)
110+
DB.Preload("Pets.Toy").Find(&user2, "\"id\" = ?", user.ID)
111111
CheckUser(t, user2, user)
112112

113113
var user3 User
114-
DB.Preload(clause.Associations+"."+clause.Associations).Find(&user3, "id = ?", user.ID)
114+
DB.Preload(clause.Associations+"."+clause.Associations).Find(&user3, "\"id\" = ?", user.ID)
115115
CheckUser(t, user3, user)
116116

117117
var user4 *User
118-
DB.Preload("Pets.Toy").Find(&user4, "id = ?", user.ID)
118+
DB.Preload("Pets.Toy").Find(&user4, "\"id\" = ?", user.ID)
119119
CheckUser(t, *user4, user)
120120
}
121121

@@ -167,7 +167,7 @@ func TestPreloadWithConds(t *testing.T) {
167167
}
168168

169169
var users2 []User
170-
DB.Preload("Account", clause.Eq{Column: "number", Value: users[0].Account.AccountNumber}).Find(&users2, "id IN ?", userIDs)
170+
DB.Preload("Account", clause.Eq{Column: "account_number", Value: users[0].Account.AccountNumber}).Find(&users2, "id IN ?", userIDs)
171171
sort.Slice(users2, func(i, j int) bool {
172172
return users2[i].ID < users2[j].ID
173173
})
@@ -232,7 +232,7 @@ func TestNestedPreloadWithConds(t *testing.T) {
232232
}
233233

234234
var users2 []User
235-
DB.Preload("Pets.Toy", "name like ?", `%preload_3`).Find(&users2, "id IN ?", userIDs)
235+
DB.Preload("Pets.Toy", "\"name\" like ?", `%preload_3`).Find(&users2, "\"id\" IN ?", userIDs)
236236

237237
for idx, user := range users2[0:2] {
238238
for _, pet := range user.Pets {
@@ -312,8 +312,8 @@ func TestPreloadWithDiffModel(t *testing.T) {
312312
User
313313
}
314314

315-
DB.Model(User{}).Preload("Account", clause.Eq{Column: "number", Value: user.Account.AccountNumber}).Select(
316-
"users.*, 'yo' as something").First(&result, "name = ?", user.Name)
315+
DB.Model(User{}).Preload("Account", clause.Eq{Column: "\"account_number\"", Value: user.Account.AccountNumber}).Select(
316+
"\"users\".*, 'yo' as something").First(&result, "\"name\" = ?", user.Name)
317317

318318
CheckUser(t, user, result.User)
319319
}
@@ -330,29 +330,29 @@ func TestNestedPreloadWithUnscoped(t *testing.T) {
330330
}
331331

332332
var user2 User
333-
DB.Preload("Pets.Toy").Find(&user2, "id = ?", user.ID)
333+
DB.Preload("Pets.Toy").Find(&user2, "\"id\" = ?", user.ID)
334334
CheckUser(t, user2, user)
335335

336336
DB.Delete(&pet)
337337

338338
var user3 User
339-
DB.Preload(clause.Associations+"."+clause.Associations).Find(&user3, "id = ?", user.ID)
339+
DB.Preload(clause.Associations+"."+clause.Associations).Find(&user3, "\"id\" = ?", user.ID)
340340
if len(user3.Pets) != 0 {
341341
t.Fatalf("User.Pet[0] was deleted and should not exist.")
342342
}
343343

344344
var user4 *User
345-
DB.Preload("Pets.Toy").Find(&user4, "id = ?", user.ID)
345+
DB.Preload("Pets.Toy").Find(&user4, "\"id\" = ?", user.ID)
346346
if len(user4.Pets) != 0 {
347347
t.Fatalf("User.Pet[0] was deleted and should not exist.")
348348
}
349349

350350
var user5 User
351-
DB.Unscoped().Preload(clause.Associations+"."+clause.Associations).Find(&user5, "id = ?", user.ID)
351+
DB.Unscoped().Preload(clause.Associations+"."+clause.Associations).Find(&user5, "\"id\" = ?", user.ID)
352352
CheckUserUnscoped(t, user5, user)
353353

354354
var user6 *User
355-
DB.Unscoped().Preload("Pets.Toy").Find(&user6, "id = ?", user.ID)
355+
DB.Unscoped().Preload("Pets.Toy").Find(&user6, "\"id\" = ?", user.ID)
356356
CheckUserUnscoped(t, *user6, user)
357357
}
358358

tests/run-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ echo "Processing tests from passed-tests.txt..."
4040
echo ""
4141

4242
# Read the file line by line
43-
while IFS= read -r line; do
43+
while IFS= read -r line || [[ -n "$line" ]]; do
4444
# Skip empty lines - keep them as is
4545
if [[ -z "$line" ]]; then
4646
echo "$line" >> "$temp_file"

tests/sql_injection_test.go

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
** Copyright (c) 2025 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package tests
40+
41+
import (
42+
"fmt"
43+
"testing"
44+
)
45+
46+
type TestUser struct {
47+
ID uint `gorm:"primaryKey"`
48+
Username string `gorm:"uniqueIndex"`
49+
Email string
50+
Password string
51+
Role string
52+
}
53+
54+
var sqlInjectionTestCases = []string{
55+
"admin'; DROP TABLE \"test_users\"; --",
56+
"admin' UNION SELECT 1,\"username\",\"password\",1,1 FROM \"test_users\" --",
57+
"admin' AND 1=1 --",
58+
"admin' OR '1'='1' --",
59+
"admin' AND 1=2 --",
60+
"admin' OR '1'='2' --",
61+
"admin'; WAITFOR DELAY '00:00:05' --",
62+
"admin' AND (SELECT COUNT(*) FROM user_tables) > 0 --",
63+
"admin'; INSERT INTO \"test_users\" (\"username\",\"email\",\"role\") VALUES ('hacker','[email protected]','admin'); --",
64+
"admin' --",
65+
"admin\x00", // Null byte injection
66+
"0x61646D696E", // Hexadecimal representation of "admin"
67+
"admin%27%20OR%201%3D1%20--", // URL-encoded injection "admin' OR 1=1 --"
68+
}
69+
70+
func TestRawQueryInjection(t *testing.T) {
71+
if err := DB.AutoMigrate(&TestUser{}); err != nil {
72+
t.Errorf("failed to create test table: %v", err)
73+
}
74+
75+
testUsers := []TestUser{
76+
{Username: "admin", Email: "[email protected]", Password: "admin123", Role: "admin"},
77+
{Username: "user1", Email: "[email protected]", Password: "user123", Role: "user"},
78+
}
79+
for _, user := range testUsers {
80+
DB.FirstOrCreate(&user, TestUser{Username: user.Username})
81+
}
82+
for _, test := range sqlInjectionTestCases {
83+
var testUser []TestUser
84+
result := DB.Raw("SELECT * FROM \"test_users\" WHERE \"username\" = ?", test).Scan(&testUser)
85+
if result.Error == nil && len(testUser) > 0 {
86+
t.Errorf("Query should fail or returned no results: %v", result.Error)
87+
}
88+
89+
if !DB.Migrator().HasTable(&TestUser{}) {
90+
t.Errorf("Test table 'test_users' does not exist after migration")
91+
}
92+
93+
var count int64
94+
DB.Model(&TestUser{}).Where("\"username\" = ?", "hacker").Count(&count)
95+
if count > 0 {
96+
t.Errorf("Unexpected user 'hacker' was found!")
97+
}
98+
99+
var rowCount int64
100+
DB.Model(&TestUser{}).Count(&rowCount)
101+
if rowCount != 2 {
102+
t.Errorf("Expected user table to have 2 rows, but found %d", rowCount)
103+
}
104+
}
105+
DB.Migrator().DropTable(&TestUser{})
106+
}
107+
108+
func TestWhereClauseInjection(t *testing.T) {
109+
if err := DB.AutoMigrate(&TestUser{}); err != nil {
110+
t.Errorf("failed to create test table: %v", err)
111+
}
112+
113+
testUsers := []TestUser{
114+
{Username: "admin", Email: "[email protected]", Password: "admin123", Role: "admin"},
115+
{Username: "user1", Email: "[email protected]", Password: "user123", Role: "user"},
116+
}
117+
for _, user := range testUsers {
118+
DB.FirstOrCreate(&user, TestUser{Username: user.Username})
119+
}
120+
for _, test := range sqlInjectionTestCases {
121+
var testUser []TestUser
122+
result := DB.Where("\"username\" = ?", test).Find(&testUsers)
123+
if result.Error == nil && len(testUser) > 0 {
124+
t.Errorf("Query should fail or returned no results: %v", result.Error)
125+
}
126+
127+
if !DB.Migrator().HasTable(&TestUser{}) {
128+
t.Errorf("Test table 'test_users' does not exist after migration")
129+
}
130+
131+
var count int64
132+
DB.Model(&TestUser{}).Where("\"username\" = ?", "hacker").Count(&count)
133+
if count > 0 {
134+
t.Errorf("Unexpected user 'hacker' was found!")
135+
}
136+
137+
var rowCount int64
138+
DB.Model(&TestUser{}).Count(&rowCount)
139+
if rowCount != 2 {
140+
t.Errorf("Expected user table to have 2 rows, but found %d", rowCount)
141+
}
142+
}
143+
DB.Migrator().DropTable(&TestUser{})
144+
}
145+
146+
func TestUpdateInjection(t *testing.T) {
147+
if err := DB.AutoMigrate(&TestUser{}); err != nil {
148+
t.Errorf("failed to create test table: %v", err)
149+
}
150+
151+
testUser := TestUser{Username: "updatetest", Email: "[email protected]", Role: "user"}
152+
DB.Create(&testUser)
153+
154+
for _, test := range sqlInjectionTestCases {
155+
DB.Model(&testUser).Where("\"id\" = ?", testUser.ID).Update("email", test)
156+
var user TestUser
157+
result := DB.Where("username = ?", "updatetest").First(&user)
158+
if result.Error == nil && user.Email != test {
159+
t.Errorf("Expected email to be '%s', but got '%s'", test, user.Email)
160+
}
161+
162+
if !DB.Migrator().HasTable(&TestUser{}) {
163+
t.Errorf("Test table 'test_users' does not exist after migration")
164+
}
165+
166+
var count int64
167+
DB.Model(&TestUser{}).Where("\"username\" = ?", "hacker").Count(&count)
168+
if count > 0 {
169+
t.Errorf("Unexpected user 'hacker' was found!")
170+
}
171+
172+
var rowCount int64
173+
DB.Model(&TestUser{}).Count(&rowCount)
174+
if rowCount != 1 {
175+
t.Errorf("Expected user table to have 1 rows, but found %d", rowCount)
176+
}
177+
}
178+
DB.Migrator().DropTable(&TestUser{})
179+
}
180+
181+
func TestFirstOrCreateInjection(t *testing.T) {
182+
if err := DB.AutoMigrate(&TestUser{}); err != nil {
183+
t.Errorf("failed to create test table: %v", err)
184+
}
185+
186+
for i, test := range sqlInjectionTestCases {
187+
user := TestUser{
188+
Username: test,
189+
Email: fmt.Sprintf("test%[email protected]", i),
190+
Role: "user",
191+
}
192+
DB.FirstOrCreate(&user, TestUser{Username: test})
193+
194+
var count int64
195+
DB.Model(&TestUser{}).Where("\"username\" = ?", test).Count(&count)
196+
if count != 1 {
197+
t.Errorf("expected 1 record for input '%s', but found %d", test, count)
198+
}
199+
}
200+
201+
DB.Migrator().DropTable(&TestUser{})
202+
}

tests/upsert_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,11 @@ func TestFindOrCreate(t *testing.T) {
344344
}
345345

346346
DB.Where(&User{Name: "find or create embedded struct"}).Assign(User{Age: 44, Account: Account{AccountNumber: "1231231231"}, Pets: []*Pet{{Name: "first_or_create_pet1"}, {Name: "first_or_create_pet2"}}}).FirstOrCreate(&user8)
347-
if err := DB.Where("name = ?", "first_or_create_pet1").First(&Pet{}).Error; err != nil {
347+
if err := DB.Where("\"name\" = ?", "first_or_create_pet1").First(&Pet{}).Error; err != nil {
348348
t.Errorf("has many association should be saved")
349349
}
350350

351-
if err := DB.Where("number = ?", "1231231231").First(&Account{}).Error; err != nil {
351+
if err := DB.Where("\"account_number\" = ?", "1231231231").First(&Account{}).Error; err != nil {
352352
t.Errorf("belongs to association should be saved")
353353
}
354354
}

0 commit comments

Comments
 (0)