Merge pull request #14869 from rintaro/4.1-sourcekit-offset-guard

[4.1][SourceKit] Add defensive guard for invalid offset
diff --git a/test/SourceKit/CursorInfo/invalid_offset.swift b/test/SourceKit/CursorInfo/invalid_offset.swift
new file mode 100644
index 0000000..0df9650
--- /dev/null
+++ b/test/SourceKit/CursorInfo/invalid_offset.swift
@@ -0,0 +1,12 @@
+let a = 12
+
+// rdar://problem/30346106
+// Invalid offset should trigger a crash.
+
+// RUN: %sourcekitd-test \
+// RUN:   -req=open %s -- %s == \
+// RUN:   -req=edit -async -offset=0 -length=200 -replace='' %s -- %s == \
+// RUN:   -req=cursor -offset=250 %s -- %s \
+// RUN: | %FileCheck %s
+
+// CHECK: <empty cursor info>
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 096beca..5c5f1ed 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -496,6 +496,11 @@
 static StringRef getSourceToken(unsigned Offset,
                                 ImmutableTextSnapshotRef Snap) {
   auto MemBuf = Snap->getBuffer()->getInternalBuffer();
+
+  // FIXME: Invalid offset shouldn't reach here.
+  if (Offset >= MemBuf->getBufferSize())
+    return StringRef();
+
   SourceManager SM;
   auto MemBufRef = llvm::MemoryBuffer::getMemBuffer(MemBuf->getBuffer(),
                                                  MemBuf->getBufferIdentifier());