From 9b5fdb09380aa28aae2080aa0f5936e4100ab9d1 Mon Sep 17 00:00:00 2001
From: Jon Skeet <jonskeet@google.com>
Date: Wed, 30 Oct 2019 09:47:45 +0000
Subject: [PATCH] Ignore incomplete extensions when building a FileDescriptor

FileDescriptor construction uses an extension registry including extensions from imports. If these were created using an older version of protoc, the FieldDescriptor.Extension property may be null; we ignore such extensions rather than failing.
---
 csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs    | 5 +++++
 csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs | 5 ++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
index 83849a2b25..79ba13b771 100644
--- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -282,6 +282,9 @@ namespace Google.Protobuf.Reflection
 
         /// <summary>
         /// Unmodifiable list of top-level extensions declared in this file.
+        /// Note that some extensions may be incomplete (FieldDescriptor.Extension may be null)
+        /// if this descriptor was generated using a version of protoc that did not fully
+        /// support extensions in C#.
         /// </summary>
         public ExtensionCollection Extensions { get; }
 
@@ -456,6 +459,7 @@ namespace Google.Protobuf.Reflection
         {
             return descriptor.Extensions.UnorderedExtensions
                 .Select(s => s.Extension)
+                .Where(e => e != null)
                 .Concat(descriptor.Dependencies.Concat(descriptor.PublicDependencies).SelectMany(GetAllDependedExtensions))
                 .Concat(descriptor.MessageTypes.SelectMany(GetAllDependedExtensionsFromMessage));
         }
@@ -464,6 +468,7 @@ namespace Google.Protobuf.Reflection
         {
             return descriptor.Extensions.UnorderedExtensions
                 .Select(s => s.Extension)
+                .Where(e => e != null)
                 .Concat(descriptor.NestedTypes.SelectMany(GetAllDependedExtensionsFromMessage));
         }
 
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index 944f6e88d2..510c079434 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -215,7 +215,10 @@ namespace Google.Protobuf.Reflection
         public FieldCollection Fields { get; }
 
         /// <summary>
-        /// An unmodifiable list of extensions defined in this message's scrope
+        /// An unmodifiable list of extensions defined in this message's scope.
+        /// Note that some extensions may be incomplete (FieldDescriptor.Extension may be null)
+        /// if they are declared in a file generated using a version of protoc that did not fully
+        /// support extensions in C#.
         /// </summary>
         public ExtensionCollection Extensions { get; }