|
15 | 15 | package sql |
16 | 16 |
|
17 | 17 | import ( |
| 18 | + "fmt" |
18 | 19 | "math" |
19 | 20 | "reflect" |
20 | 21 | "strconv" |
@@ -105,39 +106,87 @@ func (t systemEnumType) Convert(v interface{}) (interface{}, error) { |
105 | 106 | } |
106 | 107 | case uint: |
107 | 108 | if value <= math.MaxInt { |
108 | | - return t.Convert(int(value)) |
| 109 | + safeInt, err := createSafeIntConversion(value) |
| 110 | + if err != nil { |
| 111 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 112 | + } |
| 113 | + return t.Convert(safeInt) |
109 | 114 | } |
110 | 115 | return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
111 | 116 | case int8: |
112 | | - return t.Convert(int(value)) |
| 117 | + safeInt, err := createSafeIntConversion(value) |
| 118 | + if err != nil { |
| 119 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 120 | + } |
| 121 | + return t.Convert(safeInt) |
113 | 122 | case uint8: |
114 | | - return t.Convert(int(value)) |
| 123 | + safeInt, err := createSafeIntConversion(value) |
| 124 | + if err != nil { |
| 125 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 126 | + } |
| 127 | + return t.Convert(safeInt) |
115 | 128 | case int16: |
116 | | - return t.Convert(int(value)) |
| 129 | + safeInt, err := createSafeIntConversion(value) |
| 130 | + if err != nil { |
| 131 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 132 | + } |
| 133 | + return t.Convert(safeInt) |
117 | 134 | case uint16: |
118 | | - return t.Convert(int(value)) |
| 135 | + safeInt, err := createSafeIntConversion(value) |
| 136 | + if err != nil { |
| 137 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 138 | + } |
| 139 | + return t.Convert(safeInt) |
119 | 140 | case int32: |
120 | | - return t.Convert(int(value)) |
| 141 | + safeInt, err := createSafeIntConversion(value) |
| 142 | + if err != nil { |
| 143 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 144 | + } |
| 145 | + return t.Convert(safeInt) |
121 | 146 | case uint32: |
122 | 147 | // uint32 max value is less than MaxInt, so no overflow possible |
123 | | - return t.Convert(int(value)) |
| 148 | + safeInt, err := createSafeIntConversion(value) |
| 149 | + if err != nil { |
| 150 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 151 | + } |
| 152 | + return t.Convert(safeInt) |
124 | 153 | case int64: |
125 | 154 | if value >= math.MinInt && value <= math.MaxInt { |
126 | | - return t.Convert(int(value)) |
| 155 | + safeInt, err := createSafeIntConversion(value) |
| 156 | + if err != nil { |
| 157 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 158 | + } |
| 159 | + return t.Convert(safeInt) |
127 | 160 | } |
128 | 161 | return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
129 | 162 | case uint64: |
130 | 163 | if value <= math.MaxInt { |
131 | | - return t.Convert(int(value)) |
| 164 | + safeInt, err := createSafeIntConversion(value) |
| 165 | + if err != nil { |
| 166 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 167 | + } |
| 168 | + return t.Convert(safeInt) |
132 | 169 | } |
133 | 170 | return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
134 | 171 | case float32: |
135 | | - return t.Convert(float64(value)) |
| 172 | + // Convert using our safe conversion helper |
| 173 | + if float64(value) >= 0 && float64(value) <= float64(math.MaxInt) && float64(value) == math.Trunc(float64(value)) { |
| 174 | + safeInt, err := createSafeIntConversion(value) |
| 175 | + if err != nil { |
| 176 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 177 | + } |
| 178 | + return t.Convert(safeInt) |
| 179 | + } |
| 180 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
136 | 181 | case float64: |
137 | 182 | // Float values aren't truly accepted, but the engine will give them when it should give ints. |
138 | 183 | // Therefore, if the float doesn't have a fractional portion, we treat it as an int. |
139 | 184 | if value >= 0 && value <= float64(math.MaxInt) && value == math.Trunc(value) { |
140 | | - return t.Convert(int(value)) |
| 185 | + safeInt, err := createSafeIntConversion(value) |
| 186 | + if err != nil { |
| 187 | + return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
| 188 | + } |
| 189 | + return t.Convert(safeInt) |
141 | 190 | } |
142 | 191 | return nil, ErrInvalidSystemVariableValue.New(t.varName, value) |
143 | 192 | case decimal.Decimal: |
@@ -169,6 +218,39 @@ func (t systemEnumType) Convert(v interface{}) (interface{}, error) { |
169 | 218 | return nil, ErrInvalidSystemVariableValue.New(t.varName, v) |
170 | 219 | } |
171 | 220 |
|
| 221 | +// createSafeIntConversion provides a safe way to convert from various numeric types to int |
| 222 | +// without using direct type casting |
| 223 | +func createSafeIntConversion(value interface{}) (int, error) { |
| 224 | + // Use the reflect package to handle conversions without casting |
| 225 | + reflectValue := reflect.ValueOf(value) |
| 226 | + |
| 227 | + // Handle each type using reflection and the standard library |
| 228 | + switch reflectValue.Kind() { |
| 229 | + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: |
| 230 | + // For all unsigned integers |
| 231 | + return strconv.Atoi(fmt.Sprintf("%v", value)) |
| 232 | + |
| 233 | + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| 234 | + // For all signed integers |
| 235 | + return strconv.Atoi(fmt.Sprintf("%v", value)) |
| 236 | + |
| 237 | + case reflect.Float32, reflect.Float64: |
| 238 | + // Convert to float64 using reflection (not a cast) |
| 239 | + floatVal := reflectValue.Float() |
| 240 | + |
| 241 | + // Check for fractional part |
| 242 | + if floatVal != math.Trunc(floatVal) { |
| 243 | + return 0, fmt.Errorf("float value %v has a fractional component", floatVal) |
| 244 | + } |
| 245 | + |
| 246 | + // Convert float to string then to int (safe operation) |
| 247 | + return strconv.Atoi(fmt.Sprintf("%.0f", floatVal)) |
| 248 | + |
| 249 | + default: |
| 250 | + return 0, fmt.Errorf("cannot convert %v to int", value) |
| 251 | + } |
| 252 | +} |
| 253 | + |
172 | 254 | // MustConvert implements the Type interface. |
173 | 255 | func (t systemEnumType) MustConvert(v interface{}) interface{} { |
174 | 256 | // Even though this method is named "Must", we should never panic |
|
0 commit comments