Skip to content

Commit 4d78405

Browse files
committed
Conditionalize null ptr check when casting
Background: We've noticed a lot of problems from Obj-C APIs that returned null even though they were declared to never do so. These mismatches subvert Swift's type system and can lead to hard-to-diagnose crashes much later in the program. This fatal error was introduced into the primary casting function to help catch such problems closer to the point where they occur so developers could more easily identify and fix them. However, there's been some concern about what this means for old binaries, so we're considering a check here that would allow the old behavior in certain cases yet to be determined. This PR adds the framework for such a check. Resolves rdar://72323929
1 parent 3ebd9be commit 4d78405

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

stdlib/public/runtime/DynamicCast.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sh);
110110
/// Nominal type descriptor for Swift.String.
111111
extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(SS);
112112

113+
// If this returns `true`, then we will call `fatalError` when we encounter a
114+
// null reference in a storage locaation whose type does not allow null.
115+
static bool unexpectedNullIsFatal() {
116+
return true; // Placeholder for an upcoming check.
117+
}
118+
113119
static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue,
114120
const Metadata *srcType,
115121
const Metadata *destType) {
@@ -120,12 +126,21 @@ static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue,
120126

121127
std::string srcTypeName = nameForMetadata(srcType);
122128
std::string destTypeName = nameForMetadata(destType);
123-
swift::fatalError(/* flags = */ 0,
124-
"Found unexpected null pointer value"
129+
const char *msg = "Found unexpected null pointer value"
125130
" while trying to cast value of type '%s' (%p)"
126-
" to '%s' (%p)\n",
127-
srcTypeName.c_str(), srcType,
128-
destTypeName.c_str(), destType);
131+
" to '%s' (%p)%s\n";
132+
if (unexpectedNullIsFatal()) {
133+
swift::fatalError(/* flags = */ 0, msg,
134+
srcTypeName.c_str(), srcType,
135+
destTypeName.c_str(), destType,
136+
"");
137+
} else {
138+
swift::warning(/* flags = */ 0, msg,
139+
srcTypeName.c_str(), srcType,
140+
destTypeName.c_str(), destType,
141+
": Continuing with null object, but expect problems later.");
142+
}
143+
return object;
129144
}
130145

131146
/******************************************************************************/

0 commit comments

Comments
 (0)