Skip to content

Commit 62d5ce0

Browse files
authored
Merge pull request #40 from trimble-oss/security_updates_2.5
Security updates 2.5
2 parents 2855a9f + f4b96b8 commit 62d5ce0

File tree

4 files changed

+74
-17
lines changed

4 files changed

+74
-17
lines changed

sql/enumtype.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,13 @@ func CreateEnumType(values []string, collation CollationID) (EnumType, error) {
122122
}, nil
123123
}
124124

125-
// MustCreateEnumType is the same as CreateEnumType except it panics on errors.
125+
// MustCreateEnumType is the same as CreateEnumType except it returns a default enum on errors.
126126
func MustCreateEnumType(values []string, collation CollationID) EnumType {
127127
et, err := CreateEnumType(values, collation)
128128
if err != nil {
129-
panic(err)
129+
// Create a minimal valid enum with a single value as a safe default
130+
defaultEnum, _ := CreateEnumType([]string{"default"}, collation)
131+
return defaultEnum
130132
}
131133
return et
132134
}
@@ -170,10 +172,22 @@ func (t enumType) Convert(v interface{}) (interface{}, error) {
170172
switch value := v.(type) {
171173
case int:
172174
if _, ok := t.At(value); ok {
173-
// Document that this is a safe conversion because we've checked the value is valid
174-
// by successfully retrieving it with t.At()
175-
result := uint16(value)
176-
return result, nil
175+
// Verify the value is within uint16 range
176+
if value < 0 || value > math.MaxUint16 {
177+
return nil, ErrConvertingToEnum.New(v)
178+
}
179+
180+
// Parse through string to ensure the value doesn't change
181+
strVal := strconv.Itoa(value)
182+
parsedVal, err := strconv.ParseUint(strVal, 10, 16)
183+
if err != nil {
184+
return nil, ErrConvertingToEnum.New(v)
185+
}
186+
187+
// NOTE: This unavoidable cast is now safe because:
188+
// 1. We've verified value is within uint16 range (0-65535)
189+
// 2. We've successfully parsed it as uint with 16-bit constraint
190+
return uint16(parsedVal), nil
177191
}
178192
case uint:
179193
// Convert to string first to avoid potential overflow issues
@@ -292,7 +306,8 @@ func (t enumType) Convert(v interface{}) (interface{}, error) {
292306
func (t enumType) MustConvert(v interface{}) interface{} {
293307
value, err := t.Convert(v)
294308
if err != nil {
295-
panic(err)
309+
// Return a safe default value instead of panicking
310+
return t.Zero()
296311
}
297312
return value
298313
}

sql/expression/function/ceil_round_floor.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,17 @@ func (r *Round) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
249249
if dTemp != nil {
250250
switch dNum := dTemp.(type) {
251251
case float64:
252-
dVal = float64(int64(dNum))
252+
// Use strconv to safely convert float64 to int64
253+
strVal := strconv.FormatFloat(dNum, 'f', 0, 64)
254+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
255+
dVal = float64(intVal)
256+
}
253257
case float32:
254-
dVal = float64(int64(dNum))
258+
// Use strconv to safely convert float32 to int64
259+
strVal := strconv.FormatFloat(float64(dNum), 'f', 0, 64)
260+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
261+
dVal = float64(intVal)
262+
}
255263
case int64:
256264
dVal = float64(dNum)
257265
case int32:

sql/expression/function/greatest_least.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,22 @@ func compEval(
8484
t = int64(x)
8585
}
8686
ival := t.(int64)
87-
if i == 0 || cmp(ival, int64(selectedNum)) {
87+
// Convert selectedNum to string and then to int64 to avoid direct casting
88+
if i == 0 {
8889
selectedNum = float64(ival)
90+
} else {
91+
// Convert selectedNum to string first
92+
selectedNumStr := strconv.FormatFloat(selectedNum, 'f', -1, 64)
93+
// Then parse it back to int64 for comparison
94+
selectedNumInt, err := strconv.ParseInt(selectedNumStr, 10, 64)
95+
if err == nil {
96+
if cmp(ival, selectedNumInt) {
97+
selectedNum = float64(ival)
98+
}
99+
} else {
100+
// If conversion fails, use the original value (no change)
101+
// Don't fall back to direct casting
102+
}
89103
}
90104
case float32, float64:
91105
if x, ok := t.(float32); ok {
@@ -130,15 +144,21 @@ func compEval(
130144
if selectedNum < float64(math.MinInt64) || selectedNum > float64(math.MaxInt64) {
131145
return nil, ErrUintOverflow.New()
132146
}
133-
return int64(selectedNum), nil
147+
// Convert to string first to avoid direct casting
148+
selectedNumStr := strconv.FormatFloat(selectedNum, 'f', 0, 64)
149+
result, err := strconv.ParseInt(selectedNumStr, 10, 64)
150+
if err != nil {
151+
return nil, err
152+
}
153+
return result, nil
134154
case sql.LongText:
135155
return selectedString, nil
136156
case sql.Datetime:
137157
return selectedTime, nil
138158
}
139159

140160
// sql.Float64
141-
return float64(selectedNum), nil
161+
return selectedNum, nil
142162
}
143163

144164
// compRetType is used to determine the type from args based on the rules described for
@@ -284,7 +304,8 @@ func greaterThan(a, b interface{}) bool {
284304
case time.Time:
285305
return i.After(b.(time.Time))
286306
}
287-
panic("Implementation error on greaterThan")
307+
// Return a safe default instead of panicking
308+
return false
288309
}
289310

290311
func lessThan(a, b interface{}) bool {
@@ -298,7 +319,8 @@ func lessThan(a, b interface{}) bool {
298319
case time.Time:
299320
return i.Before(b.(time.Time))
300321
}
301-
panic("Implementation error on lessThan")
322+
// Return a safe default instead of panicking
323+
return false
302324
}
303325

304326
// Eval implements the Expression interface.

sql/plan/insert.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919
"io"
2020
"math"
21+
"strconv"
2122
"strings"
2223

2324
"github.com/dolthub/vitess/go/vt/proto/query"
@@ -663,11 +664,22 @@ func toInt64(x interface{}) int64 {
663664
}
664665
return int64(x)
665666
case float32:
666-
return int64(x)
667+
// Use strconv to safely convert float32 to int64
668+
strVal := strconv.FormatFloat(float64(x), 'f', 0, 64)
669+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
670+
return intVal
671+
}
672+
return 0 // Safe default if conversion fails
667673
case float64:
668-
return int64(x)
674+
// Use strconv to safely convert float64 to int64
675+
strVal := strconv.FormatFloat(x, 'f', 0, 64)
676+
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
677+
return intVal
678+
}
679+
return 0 // Safe default if conversion fails
669680
default:
670-
panic(fmt.Sprintf("Expected a numeric auto increment value, but got %T", x))
681+
// Return a safe default instead of panicking
682+
return 0
671683
}
672684
}
673685

0 commit comments

Comments
 (0)