[ObjC] Error when appearing to use newer generated code.
There already are explicit checks in debug builds, but this adds an addition
check within all builds to catch when unknown flags are being passed to the
runtime, which is an indication that the source generation is from a newer
version of the library.
PiperOrigin-RevId: 506091257
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
index dcfbe63..130073b 100644
--- a/objectivec/GPBDescriptor.m
+++ b/objectivec/GPBDescriptor.m
@@ -140,23 +140,47 @@
fieldCount:(uint32_t)fieldCount
storageSize:(uint32_t)storageSize
flags:(GPBDescriptorInitializationFlags)flags {
+ // Compute the unknown flags by this version of the runtime and then check the passed in flags
+ // (from the generated code) to detect when sources from a newer version are being used with an
+ // older runtime.
+ GPBDescriptorInitializationFlags unknownFlags =
+ ~(GPBDescriptorInitializationFlag_FieldsWithDefault |
+ GPBDescriptorInitializationFlag_WireFormat | GPBDescriptorInitializationFlag_UsesClassRefs |
+ GPBDescriptorInitializationFlag_Proto3OptionalKnown |
+ GPBDescriptorInitializationFlag_ClosedEnumSupportKnown);
+ if ((flags & unknownFlags) != 0) {
+ GPBRuntimeMatchFailure();
+ }
NSMutableArray *fields =
(fieldCount ? [[NSMutableArray alloc] initWithCapacity:fieldCount] : nil);
BOOL fieldsIncludeDefault = (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
void *desc;
+ GPBFieldFlags mergedFieldFlags = GPBFieldNone;
for (uint32_t i = 0; i < fieldCount; ++i) {
// Need correctly typed pointer for array indexing below to work.
if (fieldsIncludeDefault) {
desc = &(((GPBMessageFieldDescriptionWithDefault *)fieldDescriptions)[i]);
+ mergedFieldFlags |=
+ (((GPBMessageFieldDescriptionWithDefault *)fieldDescriptions)[i]).core.flags;
} else {
desc = &(((GPBMessageFieldDescription *)fieldDescriptions)[i]);
+ mergedFieldFlags |= (((GPBMessageFieldDescription *)fieldDescriptions)[i]).flags;
}
GPBFieldDescriptor *fieldDescriptor =
[[GPBFieldDescriptor alloc] initWithFieldDescription:desc file:file descriptorFlags:flags];
[fields addObject:fieldDescriptor];
[fieldDescriptor release];
}
+ // No real value in checking all the fields individually, just check the combined flags at the
+ // end.
+ GPBFieldFlags unknownFieldFlags =
+ ~(GPBFieldRequired | GPBFieldRepeated | GPBFieldPacked | GPBFieldOptional |
+ GPBFieldHasDefaultValue | GPBFieldClearHasIvarOnZero | GPBFieldTextFormatNameCustom |
+ GPBFieldHasEnumDescriptor | GPBFieldMapKeyMask | GPBFieldClosedEnum);
+ if ((mergedFieldFlags & unknownFieldFlags) != 0) {
+ GPBRuntimeMatchFailure();
+ }
BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0;
GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass
@@ -834,6 +858,14 @@
count:(uint32_t)valueCount
enumVerifier:(GPBEnumValidationFunc)enumVerifier
flags:(GPBEnumDescriptorInitializationFlags)flags {
+ // Compute the unknown flags by this version of the runtime and then check the passed in flags
+ // (from the generated code) to detect when sources from a newer version are being used with an
+ // older runtime.
+ GPBEnumDescriptorInitializationFlags unknownFlags =
+ ~(GPBEnumDescriptorInitializationFlag_IsClosed);
+ if ((flags & unknownFlags) != 0) {
+ GPBRuntimeMatchFailure();
+ }
GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name
valueNames:valueNames
values:values
@@ -1072,6 +1104,15 @@
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
usesClassRefs:(BOOL)usesClassRefs {
+ // Compute the unknown options by this version of the runtime and then check the passed in
+ // descriptor's options (from the generated code) to detect when sources from a newer version are
+ // being used with an older runtime.
+ GPBExtensionOptions unknownOptions =
+ ~(GPBExtensionRepeated | GPBExtensionPacked | GPBExtensionSetWireFormat);
+ if ((desc->options & unknownOptions) != 0) {
+ GPBRuntimeMatchFailure();
+ }
+
if ((self = [super init])) {
description_ = desc;
if (!usesClassRefs) {