Skip to content

Commit

Permalink
Revert "Remove memcmp from MessagePackString. Fix #206."
Browse files Browse the repository at this point in the history
This reverts commit 208c0c7 and a part of 23effe8.
  • Loading branch information
yfakariya committed Feb 12, 2017
1 parent 6e21925 commit bf67b3b
Show file tree
Hide file tree
Showing 11 changed files with 419 additions and 18 deletions.
4 changes: 0 additions & 4 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -621,9 +621,6 @@ Release 0.9.0 beta1 2016/09/24

Release 0.9.0 beta2 2017/2/11

BREAKING CHANGES
* MessagePackObject comparison which have large binary data will be about 2x - 18x slower in .NET 3.5/4.5/4.6(other platforms will not be affected).

NEW FEATURES
* Users of serializer code generator API can specify TextWriter to output. This may improve tooling chain.
* Users of serializer code generator API can suppress [DebuggerNonUserCode] attribute to enable debugger step in.
Expand All @@ -638,7 +635,6 @@ Release 0.9.0 beta2 2017/2/11
* Fix extra field causes IndexOutOfBoundException when reflection based serializers are used. Issue #199
* Fix some built-in serializers throws InvalidOperationException instead of SerializationException for type errors. Issue #204
* Fix a combination of readonly members and collection members incorrect code generation when the type also have deserialization constructor. Issue #207.
* Fix Windows Native build error. Issue #206.
* Fix built-in collection serializers such as List<T> serializer causes SecurityException when the program run in restricted environment like Silverlight. Issue #205.
* Fix null items of complex type in List<T> or Dictionary<TKey, TValue> will not be deserialized as null. Issue #211. (from 0.8.1)
* Fix types which implement IPackable and IUnpackable but do not have any members cannot be serialized. Issue #202
3 changes: 3 additions & 0 deletions MsgPack.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsgPack.Net45", "src\MsgPack.Net45\MsgPack.Net45.csproj", "{9C7B55A6-AF7F-4D26-AB5B-297B7FF25B6D}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
CodeAnalysis|ARM = CodeAnalysis|ARM
Expand Down
3 changes: 3 additions & 0 deletions src/MsgPack.Net35/MsgPack.Net35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,9 @@
<Compile Include="..\MsgPack\UnpackingStreamReader.cs">
<Link>UnpackingStreamReader.cs</Link>
</Compile>
<Compile Include="..\MsgPack\UnsafeNativeMethods.cs">
<Link>UnsafeNativeMethods.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Validation.cs">
<Link>Validation.cs</Link>
</Compile>
Expand Down
3 changes: 3 additions & 0 deletions src/MsgPack.Net45/MsgPack.Net45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,9 @@
<Compile Include="..\MsgPack\UnpackingStreamReader.cs">
<Link>UnpackingStreamReader.cs</Link>
</Compile>
<Compile Include="..\MsgPack\UnsafeNativeMethods.cs">
<Link>UnsafeNativeMethods.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Validation.cs">
<Link>Validation.cs</Link>
</Compile>
Expand Down
6 changes: 4 additions & 2 deletions src/MsgPack.Silverlight.5/MsgPack.Silverlight.5.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU'">
<OutputPath>bin\CodeAnalysis\</OutputPath>
<DefineConstants>TRACE;SILVERLIGHT;CODE_ANALYSIS</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DocumentationFile></DocumentationFile>
<Optimize>true</Optimize>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
Expand Down Expand Up @@ -777,6 +776,9 @@
<Compile Include="..\MsgPack\UnpackingStreamReader.cs">
<Link>UnpackingStreamReader.cs</Link>
</Compile>
<Compile Include="..\MsgPack\UnsafeNativeMethods.cs">
<Link>UnsafeNativeMethods.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Serialization\LockRecursionPolicy.cs" />
<Compile Include="Serialization\ReaderWriterLockSlim.cs" />
Expand Down
3 changes: 3 additions & 0 deletions src/MsgPack.Xamarin.Android/MsgPack.Xamarin.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,9 @@
<Compile Include="..\MsgPack\UnpackingStreamReader.cs">
<Link>UnpackingStreamReader.cs</Link>
</Compile>
<Compile Include="..\MsgPack\UnsafeNativeMethods.cs">
<Link>UnsafeNativeMethods.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/MsgPack.Xamarin.iOS/MsgPack.Xamarin.iOS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,9 @@
<Compile Include="..\MsgPack\UnpackingStreamReader.cs">
<Link>UnpackingStreamReader.cs</Link>
</Compile>
<Compile Include="..\MsgPack\UnsafeNativeMethods.cs">
<Link>UnsafeNativeMethods.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
67 changes: 57 additions & 10 deletions src/MsgPack/MessagePackString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,30 @@ private static bool EqualsEncoded( MessagePackString left, MessagePackString rig
return false;
}

#if !UNITY && !WINDOWS_PHONE && !NETFX_CORE
if ( _isFastEqualsDisabled == 0 )
{
try
{
return UnsafeFastEquals( left._encoded, right._encoded );
}
catch ( SecurityException )
{
Interlocked.Exchange( ref _isFastEqualsDisabled, 1 );
}
catch ( MemberAccessException )
{
Interlocked.Exchange( ref _isFastEqualsDisabled, 1 );
}
}
#endif // if !UNITY && !WINDOWS_PHONE && !NETFX_CORE

return SlowEquals( left._encoded, right._encoded );
}

// It is 1.8x(not-aligned) - 11.1x (well-aligned) slower than memcmp, but this call is rare and it is acceptable in most cases.
// It is roughly equal to String.Equals(String).
private static bool SlowEquals( byte[] x, byte[] y )
{
if ( x.Length != y.Length )
{
return false;
}

// This looks naive, but loop expansion or unsafe code is not effect here (unsafe is more slower).

for ( var i = 0; i < x.Length; i++ )
for ( int i = 0; i < x.Length; i++ )
{
if ( x[ i ] != y[ i ] )
{
Expand All @@ -291,6 +300,44 @@ private static bool SlowEquals( byte[] x, byte[] y )
return true;
}

#if !UNITY && !WINDOWS_PHONE && !NETFX_CORE
#if SILVERLIGHT
private static int _isFastEqualsDisabled =
System.Windows.Application.Current.HasElevatedPermissions ? 0 : 1;
#else
private static int _isFastEqualsDisabled;
#endif // if SILVERLIGHT

#if DEBUG
// for testing
internal static bool IsFastEqualsDisabled
{
get { return _isFastEqualsDisabled != 0; }
}
#endif

#if !NETFX_35 && !UNITY
[SecuritySafeCritical]
#endif // !NETFX_35 && !UNITY
private static bool UnsafeFastEquals( byte[] x, byte[] y )
{
#if DEBUG
Contract.Assert( x != null, "x != null" );
Contract.Assert( y != null, "y != null" );
Contract.Assert( 0 < x.Length, "0 < x.Length" );
Contract.Assert( x.Length == y.Length, "x.Length == y.Length" );
#endif // if DEBUG
int result;
if ( !UnsafeNativeMethods.TryMemCmp( x, y, new UIntPtr( unchecked( ( uint )x.Length ) ), out result ) )
{
Interlocked.Exchange( ref _isFastEqualsDisabled, 1 );
return SlowEquals( x, y );
}

return result == 0;
}
#endif // if !UNITY && !WINDOWS_PHONE && !NETFX_CORE

#if !SILVERLIGHT && !NETSTANDARD1_1 && !NETSTANDARD1_3
[Serializable]
#endif // !SILVERLIGHT && !NETSTANDARD1_1 && !NETSTANDARD1_3
Expand Down
1 change: 1 addition & 0 deletions src/MsgPack/MsgPack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@
<Compile Include="UnpackingMode.cs" />
<Compile Include="UnpackingStream.cs" />
<Compile Include="UnpackingStreamReader.cs" />
<Compile Include="UnsafeNativeMethods.cs" />
<Compile Include="Validation.cs" />
<Compile Include="UnpackingResult.cs" />
<Compile Include="Unpacker.cs" />
Expand Down
103 changes: 103 additions & 0 deletions src/MsgPack/UnsafeNativeMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#region -- License Terms --
//
// MessagePack for CLI
//
// Copyright (C) 2010-2016 FUJIWARA, Yusuke
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion -- License Terms --

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;

namespace MsgPack
{

#if !SILVERLIGHT && !NETSTANDARD1_1 && !NETSTANDARD1_3
[SuppressUnmanagedCodeSecurity]
#endif // !SILVERLIGHT && !NETSTANDARD1_1 && !NETSTANDARD1_3
#if !NETFX_35
[SecurityCritical]
#endif // !NETFX_35
internal static class UnsafeNativeMethods
{
private static int _libCAvailability = 0;
private const int _libCAvailability_Unknown = 0;
private const int _libCAvailability_MSVCRT = 1;
private const int _libCAvailability_LibC = 2;
private const int _libCAvailability_None = -1;

#if NETFX_35
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "OK, this is SecurityCritical" )]
#endif // NETFX_35
[DllImport( "msvcrt", CallingConvention = CallingConvention.Cdecl, EntryPoint = "memcmp", ExactSpelling = true, SetLastError = false )]
private static extern int memcmpVC( byte[] s1, byte[] s2, /*SIZE_T*/UIntPtr size );

#if !NETFX_CORE
// libc is for non Windows environment.
// Note that libc caused compilation error on .NET Native, so the DllImport itself should not be included in the first time.
#if NETFX_35
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "OK, this is SecurityCritical" )]
#endif // NETFX_35
[DllImport( "libc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "memcmp", ExactSpelling = true, SetLastError = false )]
private static extern int memcmpLibC( byte[] s1, byte[] s2, /*SIZE_T*/UIntPtr size );
#endif // !NETFX_CORE

public static bool TryMemCmp( byte[] s1, byte[] s2, /*SIZE_T*/UIntPtr size, out int result )
{
if ( _libCAvailability < 0 )
{
result = 0;
return false;
}

if ( _libCAvailability <= _libCAvailability_MSVCRT )
{
try
{
result = memcmpVC( s1, s2, size );
return true;
}
catch ( DllNotFoundException )
{
#if !NETFX_CORE
Interlocked.Exchange( ref _libCAvailability, _libCAvailability_LibC );
#else
Interlocked.Exchange( ref _libCAvailability, _libCAvailability_None );
#endif // !NETFX_CORE
}
}

#if !NETFX_CORE
if ( _libCAvailability <= _libCAvailability_LibC )
{
try
{
result = memcmpLibC( s1, s2, size );
return true;
}
catch ( DllNotFoundException )
{
Interlocked.Exchange( ref _libCAvailability, _libCAvailability_None );
}
}
#endif // !NETFX_CORE

result = 0;
return false;
}
}
}
Loading

0 comments on commit bf67b3b

Please sign in to comment.