KEMBAR78
BadImageFormatException : Bad IL format when using `base` · Issue #13926 · dotnet/fsharp · GitHub
Skip to content

BadImageFormatException : Bad IL format when using base #13926

@abelbraaksma

Description

@abelbraaksma

Using base.XXX to call a base method causes a BadImageFormatException to be raised.

EDIT: it looks like F# allowing me to call an abstract method, as the base class is abstract. This, I believe, should not be allowed and JIT therefore throws a BadImageFormatException. If you try to write code in F# with an AbstractClass and a derived class, you'd receive a normal compile-time error.

Repro steps

The following code (requires Giraffe and FsUnit to run the test) throws a BadImageFormatException

namespace Test

open Giraffe
open Xunit
open FsUnit.Xunit

open System.Text.Json
open System.Text.Json.Serialization

type StringTrimJsonSerializer(o: JsonSerializerOptions) =
    inherit JsonConverter<string>()

    override this.Read(reader, _, _) =
        match reader.TokenType with
        | JsonTokenType.String -> reader.GetString().Trim()
        | _ -> JsonException("Type is not a string") |> raise

    /// This causes a BadImageFormatException
    override this.Write(writer, objectToWrite, options) = base.Write(writer, objectToWrite, options)


module SerializationTests =

    type SomeType = { Amount: decimal; Currency: string }

    let serialize item =
        let options = SystemTextJson.Serializer.DefaultOptions
        StringTrimJsonSerializer options |> options.Converters.Add
        JsonSerializer.Serialize(item, options)

    let deserialize<'T> (stringValue: string) =
        let options = SystemTextJson.Serializer.DefaultOptions
        StringTrimJsonSerializer options |> options.Converters.Add
        JsonSerializer.Deserialize<'T>(stringValue, options)

    [<Fact>]
    let ``Roundtip type should trim currency whitespace`` () =
        { Amount = 42.99M; Currency = "  USD   " }
        |> serialize
        |> deserialize<SomeType>
        |> should equal { Amount = 42.99M; Currency = "USD" }

Expected behavior

Should call the base method or give compile error if such method doesn't exist.

Actual behavior

Throws:

BadImageFormatException : Bad IL format.

Known workarounds

Don't use base in a derived method.

Related information

On dotnet 6, using System.Text.Json serialization BCL classes, Windows 10/11.

EDIT, the IL of the offending code looks as follows (Release build):

.method public hidebysig virtual 
	instance void Write (
		class [System.Text.Json]System.Text.Json.Utf8JsonWriter writer,
		string objectToWrite,
		class [System.Text.Json]System.Text.Json.JsonSerializerOptions options
	) cil managed 
{
	// Method begins at RVA 0x316c
	// Header size: 1
	// Code size: 10 (0xa)
	.maxstack 8

	// base.Write(writer, objectToWrite, options);
	IL_0000: ldarg.0
	IL_0001: ldarg.1
	IL_0002: ldarg.2
	IL_0003: ldarg.3
	IL_0004: call instance void class [System.Text.Json]System.Text.Json.Serialization.JsonConverter`1<string>::Write(class [System.Text.Json]System.Text.Json.Utf8JsonWriter, !0, class [System.Text.Json]System.Text.Json.JsonSerializerOptions)
	// }
	IL_0009: ret
} 

Metadata

Metadata

Assignees

Labels

Area-Compiler-CheckingType checking, attributes and all aspects of logic checkingBugImpact-Medium(Internal MS Team use only) Describes an issue with moderate impact on existing code.

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions