Skip to content

[s390x] Undefined behaviour in float32 #107387

@saitama951

Description

@saitama951

Recently we started seeing test case failures relating to System.Buffers.Binary.Tests.BinaryWriterUnitTests.SpanWriteSingle
Test case:

   public void SpanWriteSingle(float value)
   {
            var value = float.NegativeInfinity;
            WriteSingleLittleEndian(span, value);
            read = ReadSingleLittleEndian(span);
            Assert.Equal(value, read);
   }

the corresponding tests fails with

  Error Message:
Assert.Equal() Failure: Values differ
Expected: -∞
Actual:   ∞
Stack Trace:
  at System.Buffers.Binary.Tests.BinaryWriterUnitTests.SpanWriteSingle(Single value) in /home/sanjam/repro/runtime/src/libraries/System.Memory/tests/Binary/BinaryWriterUnitTests.cs:line 335
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) in /home/sanjam/repro/runtime/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs:line 22
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr) in /home/sanjam/repro/runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 174

I had extracted out the test case for my simplicity with various console printing

using System.Reflection;
using System;
using System.Runtime.InteropServices;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
class Attribute
{
        public static void Main(string [] args)
        {
                var span = new Span<byte>(new byte[4]);
                float value = float.NegativeInfinity;
                Console.WriteLine("float: "+value);
                BinaryPrimitives.WriteSingleLittleEndian(span, value);
                int temp=0;
                if (!BitConverter.IsLittleEndian){
                temp = BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read<int>(span));
                //Console.WriteLine("value of temp: "+temp);
                }
                unsafe{
                Console.WriteLine("Int32ToSingle  " + BitConverter.Int32BitsToSingle(temp));
                //Console.WriteLine("bitcast: "+Unsafe.BitCast<int,float>(temp)); //Unsafe.Bitcase -> ReadUnaligned+Unsafe.As
                //Console.WriteLine("As: "+Unsafe.As<int,byte>(ref temp));
                //Console.WriteLine("ReadUnaligned: "+Unsafe.ReadUnaligned<float> ( ref Unsafe.As<int,byte>(ref temp)));
                }
                /*Console.WriteLine("span: "+span[0]+""+span[1]+""+span[2]+""+span[3]);
                Console.WriteLine(read);*/

        }

}


the following program gives me the expected output

[root@sanjam findhash]# dotnet bin/Debug/net9.0/findhash.dll
float: -∞
Int32ToSingle  ∞

when Uncommenting the a simple Console.WriteLine from the if condition the output changes.

using System.Reflection;
using System;
using System.Runtime.InteropServices;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
class Attribute
{
        public static void Main(string [] args)
        {
                var span = new Span<byte>(new byte[4]);
                float value = float.NegativeInfinity;
                Console.WriteLine("float: "+value);
                BinaryPrimitives.WriteSingleLittleEndian(span, value);
                int temp=0;
                if (!BitConverter.IsLittleEndian){
                temp = BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read<int>(span));
                Console.WriteLine("value of temp: "+temp);  //UNCOMMENTED LINE
                }
                unsafe{
                Console.WriteLine("Int32ToSingle  " + BitConverter.Int32BitsToSingle(temp));
                //Console.WriteLine("bitcast: "+Unsafe.BitCast<int,float>(temp)); //Unsafe.Bitcase -> ReadUnaligned+Unsafe.As
                //Console.WriteLine("As: "+Unsafe.As<int,byte>(ref temp));
                //Console.WriteLine("ReadUnaligned: "+Unsafe.ReadUnaligned<float> ( ref Unsafe.As<int,byte>(ref temp)));
                }

        }

}

output:

[root@sanjam findhash]# dotnet bin/Debug/net9.0/findhash.dll
float: -∞
value of temp: -8388608
Int32ToSingle  -∞

cc: @giritrivedi @omajid @uweigand @iii-i

Metadata

Metadata

Assignees

No one assigned

    Labels

    arch-s390xRelated to s390x architecture (unsupported)area-Codegen-JIT-monoin-prThere is an active PR which will close this issue when it is merged

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions