diff --git a/src/mono/mono/mini/ir-emit.h b/src/mono/mono/mini/ir-emit.h
index 937222f568c22e..9165de198f19d8 100644
--- a/src/mono/mono/mini/ir-emit.h
+++ b/src/mono/mono/mini/ir-emit.h
@@ -882,6 +882,13 @@ static int ccount = 0;
#define MONO_EMIT_NEW_IMPLICIT_EXCEPTION_LOAD_STORE(cfg) do { \
} while (0)
+#define MONO_EMIT_EXPLICIT_NULL_CHECK(cfg, reg) do { \
+ cfg->flags |= MONO_CFG_HAS_CHECK_THIS; \
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, (reg), 0); \
+ MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); \
+ MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, reg); \
+ } while (0)
+
/* Emit an explicit null check which doesn't depend on SIGSEGV signal handling */
#define MONO_EMIT_NULL_CHECK(cfg, reg, out_of_page) do { \
if (cfg->explicit_null_checks || (out_of_page)) { \
diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c
index 3ed3f1054830e3..9e67f9969e88da 100644
--- a/src/mono/mono/mini/method-to-ir.c
+++ b/src/mono/mono/mini/method-to-ir.c
@@ -10026,6 +10026,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
EMIT_NEW_BIALU_IMM (cfg, ptr, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
store = mini_emit_storing_write_barrier (cfg, ptr, sp [1]);
} else {
+ if (MONO_TYPE_ISSTRUCT (field->type))
+ /* The decomposition might end up calling a copy/wbarrier function which doesn't do null checks */
+ MONO_EMIT_EXPLICIT_NULL_CHECK (cfg, sp [0]->dreg);
+
EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
}
}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs
new file mode 100644
index 00000000000000..110ea1d0d802b1
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.Runtime.CompilerServices;
+
+public class Program
+{
+ public Program()
+ {
+ }
+
+ static int Main(string[] args)
+ {
+ Foo currentFoo;
+
+ Bacon defaultBacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false);
+ currentFoo = new Foo();
+ try {
+ currentFoo.GetBar().m_Bacon = defaultBacon;
+ } catch (NullReferenceException) {
+ return 100;
+ }
+ return 101;
+ }
+}
+
+public class Foo
+{
+ private Bar m_Bar;
+ public Bar GetBar()
+ {
+ return m_Bar;
+ }
+}
+
+
+public class Bar
+{
+ public Bacon m_Bacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false);
+}
+
+public struct Bacon
+{
+ public float Value;
+ public enum FooEnum
+ {
+ One,
+ Two
+ };
+
+ public FooEnum m_FooEnum;
+ public float m_f1;
+ public float m_f2;
+ public float m_f3;
+ public string m_s1;
+ public float m_f8;
+ public bool m_bool1;
+ public float m_f4;
+ public float m_f5;
+ public bool m_bool2;
+ public FooBar m_FooBar;
+
+ float m_f6;
+ float m_f7;
+ int m_i1;
+
+ public bool bool3 { get; set; }
+
+ public bool bool4 { get; set; }
+
+ public interface IFooInterface
+ {
+ float GetFooValue(int foo);
+ }
+
+ IFooInterface m_FooProvider;
+ int m_i2;
+
+ public Bacon(
+ float minValue, float maxValue, bool wrap, bool rangeLocked,
+ float maxSpeed, float accelTime, float decelTime,
+ string name, bool invert)
+ {
+ m_f4 = minValue;
+ m_f5 = maxValue;
+ m_bool2 = wrap;
+ bool3 = rangeLocked;
+
+ bool4 = false;
+ m_FooBar = new FooBar(false, 1, 2);
+
+ m_FooEnum = FooEnum.One;
+ m_f1 = maxSpeed;
+ m_f2 = accelTime;
+ m_f3 = decelTime;
+ Value = (minValue + maxValue) / 2;
+ m_s1 = name;
+ m_f8 = 0;
+ m_bool1 = invert;
+
+ m_f6 = 0f;
+ m_FooProvider = null;
+ m_i2 = 0;
+ m_f7 = 0;
+ m_i1 = 0;
+ }
+
+ public struct FooBar
+ {
+ public bool m_FooBar_bool1;
+ public float m_FooBar_f1;
+ public float m_FooBar_f2;
+
+ float m_FooBar_f3;
+ float m_FooBar_f4;
+ float m_FooBar_f5;
+ int m_FooBar_i1;
+ int m_FooBar_i2;
+
+ public FooBar(bool b1, float f1, float f2)
+ {
+ m_FooBar_bool1 = b1;
+ m_FooBar_f1 = f1;
+ m_FooBar_f2 = f2;
+ m_FooBar_f4 = 0;
+ m_FooBar_f5 = 0;
+ m_FooBar_i1 = m_FooBar_i2 = -1;
+ m_FooBar_f3 = 0;
+ }
+ }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj
new file mode 100644
index 00000000000000..310a81f802b2e2
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj
@@ -0,0 +1,11 @@
+
+
+ Exe
+ True
+ true
+
+
+
+
+
+
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index faa84e07573118..1f8a6e84d3af50 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -66,6 +66,9 @@
https://github.com/dotnet/runtime/issues/78899
+
+ https://github.com/dotnet/runtime/pull/82663
+