Skip to content

Commit 5233c7c

Browse files
Copilotalexaka1
andcommitted
fix: validate integer/long enum values during deserialization
Use FromStringOrDefault for all numeric enum types (int, long, float, double, decimal), not just float/double/decimal. This ensures invalid values throw JsonException instead of being silently cast to the enum. Co-authored-by: alexaka1 <22166651+alexaka1@users.noreply.github.com>
1 parent 6932a22 commit 5233c7c

71 files changed

Lines changed: 718 additions & 430 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

modules/openapi-generator/src/main/resources/csharp/modelEnum.mustache

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,18 @@
155155
public override {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
156156
{
157157
{{#isInteger}}
158-
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
159-
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
160-
return result;
158+
string rawValue = reader.{{>EnumJsonReaderMethod}}().ToString(System.Globalization.CultureInfo.InvariantCulture);
159+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
160+
if (result != null)
161+
return result.Value;
162+
throw new JsonException();
161163
{{/isInteger}}
162164
{{#isLong}}
163-
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
164-
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
165-
return result;
165+
string rawValue = reader.{{>EnumJsonReaderMethod}}().ToString(System.Globalization.CultureInfo.InvariantCulture);
166+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
167+
if (result != null)
168+
return result.Value;
169+
throw new JsonException();
166170
{{/isLong}}
167171
{{#isFloat}}
168172
string rawValue = reader.GetSingle().ToString(System.Globalization.CultureInfo.InvariantCulture);
@@ -236,14 +240,18 @@
236240

237241
{{/isString}}
238242
{{#isInteger}}
239-
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
240-
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
241-
return result;
243+
string rawValue = reader.{{>EnumJsonReaderMethod}}().ToString(System.Globalization.CultureInfo.InvariantCulture);
244+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
245+
if (result != null)
246+
return result.Value;
247+
throw new JsonException();
242248
{{/isInteger}}
243249
{{#isLong}}
244-
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
245-
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
246-
return result;
250+
string rawValue = reader.{{>EnumJsonReaderMethod}}().ToString(System.Globalization.CultureInfo.InvariantCulture);
251+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
252+
if (result != null)
253+
return result.Value;
254+
throw new JsonException();
247255
{{/isLong}}
248256
{{#isFloat}}
249257
string rawValue = reader.GetSingle().ToString(System.Globalization.CultureInfo.InvariantCulture);

modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpClientCodegenTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,16 @@ public void testIntegerEnumJsonConverterUsesNumericOperations() throws IOExcepti
278278
Map<String, File> files = defaultGenerator.generate().stream()
279279
.collect(Collectors.toMap(File::getPath, Function.identity()));
280280

281-
// Verify integer enum uses numeric JSON reader/writer
281+
// Verify integer enum uses numeric JSON reader with validation
282282
File intEnumFile = files.get(Paths
283283
.get(output.getAbsolutePath(), "src", "Org.OpenAPITools", "Model", "IntegerEnum.cs")
284284
.toString()
285285
);
286286
assertNotNull(intEnumFile, "Could not find file for model: IntegerEnum");
287287
assertFileContains(intEnumFile.toPath(),
288-
"reader.GetInt32()",
288+
"reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture)",
289+
"FromStringOrDefault(rawValue)",
290+
"throw new JsonException()",
289291
"writer.WriteNumberValue(",
290292
"public static int ToJsonValue(IntegerEnum value)"
291293
);
@@ -294,14 +296,16 @@ public void testIntegerEnumJsonConverterUsesNumericOperations() throws IOExcepti
294296
"writer.WriteStringValue("
295297
);
296298

297-
// Verify long enum uses int64 reader with actual int64 values
299+
// Verify long enum uses int64 reader with validation and actual int64 values
298300
File longEnumFile = files.get(Paths
299301
.get(output.getAbsolutePath(), "src", "Org.OpenAPITools", "Model", "LongEnum.cs")
300302
.toString()
301303
);
302304
assertNotNull(longEnumFile, "Could not find file for model: LongEnum");
303305
assertFileContains(longEnumFile.toPath(),
304-
"reader.GetInt64()",
306+
"reader.GetInt64().ToString(System.Globalization.CultureInfo.InvariantCulture)",
307+
"FromStringOrDefault(rawValue)",
308+
"throw new JsonException()",
305309
"writer.WriteNumberValue(",
306310
"public static long ToJsonValue(LongEnum value)",
307311
"AboveInt32Max = 2147483648",

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/EnumTestEnumInteger.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class EnumTestEnumIntegerJsonConverter : JsonConverter<EnumTestEnumIntege
104104
/// <returns></returns>
105105
public override EnumTestEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
EnumTestEnumInteger result = (EnumTestEnumInteger)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
EnumTestEnumInteger? result = EnumTestEnumIntegerValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class EnumTestEnumIntegerNullableJsonConverter : JsonConverter<EnumTestEn
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
EnumTestEnumInteger result = (EnumTestEnumInteger)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
EnumTestEnumInteger? result = EnumTestEnumIntegerValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/EnumTestEnumIntegerOnly.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class EnumTestEnumIntegerOnlyJsonConverter : JsonConverter<EnumTestEnumIn
104104
/// <returns></returns>
105105
public override EnumTestEnumIntegerOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
EnumTestEnumIntegerOnly result = (EnumTestEnumIntegerOnly)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
EnumTestEnumIntegerOnly? result = EnumTestEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class EnumTestEnumIntegerOnlyNullableJsonConverter : JsonConverter<EnumTe
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
EnumTestEnumIntegerOnly result = (EnumTestEnumIntegerOnly)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
EnumTestEnumIntegerOnly? result = EnumTestEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/OuterEnumInteger.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ public class OuterEnumIntegerJsonConverter : JsonConverter<OuterEnumInteger>
115115
/// <returns></returns>
116116
public override OuterEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
117117
{
118-
int rawValue = reader.GetInt32();
119-
OuterEnumInteger result = (OuterEnumInteger)rawValue;
120-
return result;
118+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
119+
OuterEnumInteger? result = OuterEnumIntegerValueConverter.FromStringOrDefault(rawValue);
120+
if (result != null)
121+
return result.Value;
122+
throw new JsonException();
121123
}
122124

123125
/// <summary>
@@ -149,9 +151,11 @@ public class OuterEnumIntegerNullableJsonConverter : JsonConverter<OuterEnumInte
149151
if (reader.TokenType == JsonTokenType.Null)
150152
return null;
151153

152-
int rawValue = reader.GetInt32();
153-
OuterEnumInteger result = (OuterEnumInteger)rawValue;
154-
return result;
154+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
155+
OuterEnumInteger? result = OuterEnumIntegerValueConverter.FromStringOrDefault(rawValue);
156+
if (result != null)
157+
return result.Value;
158+
throw new JsonException();
155159
}
156160

157161
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/OuterEnumIntegerDefaultValue.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ public class OuterEnumIntegerDefaultValueJsonConverter : JsonConverter<OuterEnum
115115
/// <returns></returns>
116116
public override OuterEnumIntegerDefaultValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
117117
{
118-
int rawValue = reader.GetInt32();
119-
OuterEnumIntegerDefaultValue result = (OuterEnumIntegerDefaultValue)rawValue;
120-
return result;
118+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
119+
OuterEnumIntegerDefaultValue? result = OuterEnumIntegerDefaultValueValueConverter.FromStringOrDefault(rawValue);
120+
if (result != null)
121+
return result.Value;
122+
throw new JsonException();
121123
}
122124

123125
/// <summary>
@@ -149,9 +151,11 @@ public class OuterEnumIntegerDefaultValueNullableJsonConverter : JsonConverter<O
149151
if (reader.TokenType == JsonTokenType.Null)
150152
return null;
151153

152-
int rawValue = reader.GetInt32();
153-
OuterEnumIntegerDefaultValue result = (OuterEnumIntegerDefaultValue)rawValue;
154-
return result;
154+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
155+
OuterEnumIntegerDefaultValue? result = OuterEnumIntegerDefaultValueValueConverter.FromStringOrDefault(rawValue);
156+
if (result != null)
157+
return result.Value;
158+
throw new JsonException();
155159
}
156160

157161
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNotnullableEnumInteger.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerJsonConverter : JsonConv
104104
/// <returns></returns>
105105
public override RequiredClassRequiredNotnullableEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
RequiredClassRequiredNotnullableEnumInteger result = (RequiredClassRequiredNotnullableEnumInteger)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
RequiredClassRequiredNotnullableEnumInteger? result = RequiredClassRequiredNotnullableEnumIntegerValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerNullableJsonConverter :
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
RequiredClassRequiredNotnullableEnumInteger result = (RequiredClassRequiredNotnullableEnumInteger)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
RequiredClassRequiredNotnullableEnumInteger? result = RequiredClassRequiredNotnullableEnumIntegerValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNotnullableEnumIntegerOnly.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerOnlyJsonConverter : Json
104104
/// <returns></returns>
105105
public override RequiredClassRequiredNotnullableEnumIntegerOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
RequiredClassRequiredNotnullableEnumIntegerOnly result = (RequiredClassRequiredNotnullableEnumIntegerOnly)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
RequiredClassRequiredNotnullableEnumIntegerOnly? result = RequiredClassRequiredNotnullableEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerOnlyNullableJsonConverte
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
RequiredClassRequiredNotnullableEnumIntegerOnly result = (RequiredClassRequiredNotnullableEnumIntegerOnly)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
RequiredClassRequiredNotnullableEnumIntegerOnly? result = RequiredClassRequiredNotnullableEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNullableEnumInteger.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class RequiredClassRequiredNullableEnumIntegerJsonConverter : JsonConvert
104104
/// <returns></returns>
105105
public override RequiredClassRequiredNullableEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
RequiredClassRequiredNullableEnumInteger result = (RequiredClassRequiredNullableEnumInteger)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
RequiredClassRequiredNullableEnumInteger? result = RequiredClassRequiredNullableEnumIntegerValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class RequiredClassRequiredNullableEnumIntegerNullableJsonConverter : Jso
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
RequiredClassRequiredNullableEnumInteger result = (RequiredClassRequiredNullableEnumInteger)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
RequiredClassRequiredNullableEnumInteger? result = RequiredClassRequiredNullableEnumIntegerValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNullableEnumIntegerOnly.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ public class RequiredClassRequiredNullableEnumIntegerOnlyJsonConverter : JsonCon
104104
/// <returns></returns>
105105
public override RequiredClassRequiredNullableEnumIntegerOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106106
{
107-
int rawValue = reader.GetInt32();
108-
RequiredClassRequiredNullableEnumIntegerOnly result = (RequiredClassRequiredNullableEnumIntegerOnly)rawValue;
109-
return result;
107+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
108+
RequiredClassRequiredNullableEnumIntegerOnly? result = RequiredClassRequiredNullableEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
109+
if (result != null)
110+
return result.Value;
111+
throw new JsonException();
110112
}
111113

112114
/// <summary>
@@ -138,9 +140,11 @@ public class RequiredClassRequiredNullableEnumIntegerOnlyNullableJsonConverter :
138140
if (reader.TokenType == JsonTokenType.Null)
139141
return null;
140142

141-
int rawValue = reader.GetInt32();
142-
RequiredClassRequiredNullableEnumIntegerOnly result = (RequiredClassRequiredNullableEnumIntegerOnly)rawValue;
143-
return result;
143+
string rawValue = reader.GetInt32().ToString(System.Globalization.CultureInfo.InvariantCulture);
144+
RequiredClassRequiredNullableEnumIntegerOnly? result = RequiredClassRequiredNullableEnumIntegerOnlyValueConverter.FromStringOrDefault(rawValue);
145+
if (result != null)
146+
return result.Value;
147+
throw new JsonException();
144148
}
145149

146150
/// <summary>

0 commit comments

Comments
 (0)