pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
// stack: StringBuilder length
-
- // if (!fConvertSpaceJustCalled)
- {
- // we don't need to double-check the length because the length
- // must be smaller than the capacity and the capacity was already
- // checked by EmitConvertSpaceCLRToNative
-
- pslILEmit->EmitDUP();
- // static void StubHelpers.CheckStringLength(int length)
- pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
- }
+ pslILEmit->EmitDUP();
+ // static void StubHelpers.CheckStringLength(int length)
+ pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
// stack: StringBuilder length
return TRUE;
}
+
+// Verify that we append extra null terminators to our StringBuilder native buffers.
+// Although this is a hidden implementation detail, it would be breaking behavior to stop doing this
+// so we have a test for it. In particular, this detail prevents us from optimizing marshalling StringBuilders by pinning.
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Verify_NullTerminators_PastEnd(LPCWSTR buffer, int length)
+{
+ return buffer[length+1] == W('\0');
+}
[DllImport(NativeBinaryName)]
public static extern bool ReverseP_MarshalStrB_InOut(Del_MarshalStrB_InOut d, [MarshalAs(UnmanagedType.LPTStr)]string s);
+ [DllImport(NativeBinaryName)]
+ public static extern bool Verify_NullTerminators_PastEnd(StringBuilder builder, int length);
+
+ [DllImport(NativeBinaryName, EntryPoint = "Verify_NullTerminators_PastEnd")]
+ public static extern bool Verify_NullTerminators_PastEnd_Out([Out] StringBuilder builder, int length);
}
-}
\ No newline at end of file
+}