Xcode 9 throws errors involving 'require'

匿名 (未验证) 提交于 2019-12-03 03:06:01

问题:

When upgrading code to build under Xcode 9, I see compile errors in code using require and require_noerr:

    require(length > offsetof(struct blob, cert), outLabel); 

The first error is: error: implicit declaration of function 'require' is invalid in C99

I also get a lot of error: use of undeclared identifier 'outLabel'. This is in RRTransactionVerifier.m which is Apple code for dealing with receipt validation.

How do I fix these errors?

回答1:

require and require_noerr are macros that used to be defined in AssertMacros.h. As of Xcode 9 these macros have changed.

The reasons are documented in that header file:

For time immemorial, Mac OS X has defined version of most of these macros without the __ prefix, which could collide with similarly named functions or macros in user code, including new functionality in Boost and the C++ standard library.

macOS High Sierra and iOS 11 will now require that clients move to the new macros as defined above.

If you would like to enable the macros for use within your own project, you can define the __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES macro via an Xcode Build Configuration. See "Add a build configuration (xcconfig) file" in Xcode Help.

So to fix the issue you can set that define, or change your code to use the new macros. require is now __Require, require_noerr is now __Require_noErr, and so on. They provide a script in the header file on how to change your code via a script:

EDIT: Added one backslash in the end of the script's first line, otherwise Terminal would break the command into two.

/* To aid users of these macros in converting their sources, the following tops script  will convert usages of the old macros into the new equivalents.  To do so, in Terminal  go into the directory containing the sources to be converted and run this command.  find . -name '*.[c|cc|cp|cpp|m|mm|h]' -print0 |  xargs -0 tops \ -verbose \       replace "check(<b args>)" with "__Check(<args>)" \       replace "check_noerr(<b args>)" with "__Check_noErr(<args>)" \       replace "check_noerr_string(<b args>)" with "__Check_noErr_String(<args>)" \       replace "check_string(<b args>)" with "__Check_String(<args>)" \       replace "require(<b args>)" with "__Require(<args>)" \       replace "require_action(<b args>)" with "__Require_Action(<args>)" \       replace "require_action_string(<b args>)" with "__Require_Action_String(<args>)" \       replace "require_noerr(<b args>)" with "__Require_noErr(<args>)" \       replace "require_noerr_action(<b args>)" with "__Require_noErr_Action(<args>)" \       replace "require_noerr_action_string(<b args>)" with "__Require_noErr_Action_String(<args>)" \       replace "require_noerr_string(<b args>)" with "__Require_noErr_String(<args>)" \       replace "require_string(<b args>)" with "__Require_String(<args>)" \       replace "verify(<b args>)" with "__Verify(<args>)" \       replace "verify_action(<b args>)" with "__Verify_Action(<args>)" \       replace "verify_noerr(<b args>)" with "__Verify_noErr(<args>)" \       replace "verify_noerr_action(<b args>)" with "__Verify_noErr_Action(<args>)" \       replace "verify_noerr_string(<b args>)" with "__Verify_noErr_String(<args>)" \       replace "verify_string(<b args>)" with "__Verify_String(<args>)" \       replace "ncheck(<b args>)" with "__nCheck(<args>)" \       replace "ncheck_string(<b args>)" with "__nCheck_String(<args>)" \       replace "nrequire(<b args>)" with "__nRequire(<args>)" \       replace "nrequire_action(<b args>)" with "__nRequire_Action(<args>)" \       replace "nrequire_action_quiet(<b args>)" with "__nRequire_Action_Quiet(<args>)" \       replace "nrequire_action_string(<b args>)" with "__nRequire_Action_String(<args>)" \       replace "nrequire_quiet(<b args>)" with "__nRequire_Quiet(<args>)" \       replace "nrequire_string(<b args>)" with "__nRequire_String(<args>)" \       replace "nverify(<b args>)" with "__nVerify(<args>)" \       replace "nverify_string(<b args>)" with "__nVerify_String(<args>)" \       replace "require_action_quiet(<b args>)" with "__Require_Action_Quiet(<args>)" \       replace "require_noerr_action_quiet(<b args>)" with "__Require_noErr_Action_Quiet(<args>)" \       replace "require_noerr_quiet(<b args>)" with "__Require_noErr_Quiet(<args>)" \       replace "require_quiet(<b args>)" with "__Require_Quiet(<args>)" \       replace "check_compile_time(<b args>)" with "__Check_Compile_Time(<args>)" \       replace "debug_string(<b args>)" with "__Debug_String(<args>)" */ 


回答2:

In /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ MacOSX10.11.sdk/usr/include/AssertMacros.h require, require_noerr macros are modified now.

Follow this link: https://github.com/fontforge/fontforge/issues/3164 to check the changed list. For your error, problem is in this method. This is the modified method in VerificationController.m.

  BOOL checkReceiptSecurity(NSString *purchase_info_string, NSString *signature_string, CFDateRef purchaseDate) { BOOL valid = NO; SecCertificateRef leaf = NULL, intermediate = NULL; SecTrustRef trust = NULL; SecPolicyRef policy = SecPolicyCreateBasicX509();  NSData *certificate_data; NSArray *anchors;  /*  Parse inputs:  purchase_info_string and signature_string are base64 encoded JSON blobs that need to  be decoded.  */  __Require([purchase_info_string canBeConvertedToEncoding:NSASCIIStringEncoding] &&         [signature_string canBeConvertedToEncoding:NSASCIIStringEncoding], outLabel);  size_t purchase_info_length; uint8_t *purchase_info_bytes = base64_decode([purchase_info_string cStringUsingEncoding:NSASCIIStringEncoding],                                              &purchase_info_length);  size_t signature_length; uint8_t *signature_bytes = base64_decode([signature_string cStringUsingEncoding:NSASCIIStringEncoding],                                          &signature_length);  __Require(purchase_info_bytes && signature_bytes, outLabel);  /*  Binary format looks as follows:   RECEIPTVERSION | SIGNATURE | CERTIFICATE SIZE | CERTIFICATE  1 byte           128         4 bytes  big endian   Extract version, signature and certificate(s).  Check receipt version == 2.  Sanity check that signature is 128 bytes.  Sanity check certificate size <= remaining payload data.  */   #pragma pack(push, 1) struct signature_blob {     uint8_t version;     uint8_t signature[128];     uint32_t cert_len;     uint8_t certificate[]; } *signature_blob_ptr = (struct signature_blob *)signature_bytes;  #pragma pack(pop) uint32_t certificate_len;  /*  Make sure the signature blob is long enough to safely extract the version and  cert_len fields, then perform a sanity check on the fields.  */ __Require(signature_length > offsetof(struct signature_blob, certificate), outLabel); __Require(signature_blob_ptr->version == 2, outLabel); certificate_len = ntohl(signature_blob_ptr->cert_len);  __Require(signature_length - offsetof(struct signature_blob, certificate) >= certificate_len, outLabel);  /*  Validate certificate chains back to valid receipt signer; policy approximation for now  set intermediate as a trust anchor; current intermediate lapses in 2016.  */  certificate_data = [NSData dataWithBytes:signature_blob_ptr->certificate length:certificate_len]; __Require(leaf = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certificate_data), outLabel);  certificate_data = [NSData dataWithBytes:iTS_intermediate_der length:iTS_intermediate_der_len]; __Require(intermediate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certificate_data), outLabel);  anchors = [NSArray arrayWithObject:(__bridge id)intermediate]; __Require(anchors, outLabel);  __Require_noErr(SecTrustCreateWithCertificates(leaf, policy, &trust), outLabel); __Require_noErr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef) anchors), outLabel);  if (purchaseDate) {     __Require_noErr(SecTrustSetVerifyDate(trust, purchaseDate), outLabel); }  SecTrustResultType trust_result; __Require_noErr(SecTrustEvaluate(trust, &trust_result), outLabel); __Require(trust_result == kSecTrustResultUnspecified, outLabel);  __Require(2 == SecTrustGetCertificateCount(trust), outLabel);  /*  Chain is valid, use leaf key to verify signature on receipt by  calculating SHA1(version|purchaseInfo)  */  CC_SHA1_CTX sha1_ctx; uint8_t to_be_verified_data[CC_SHA1_DIGEST_LENGTH];  CC_SHA1_Init(&sha1_ctx); CC_SHA1_Update(&sha1_ctx, &signature_blob_ptr->version, sizeof(signature_blob_ptr->version)); CC_SHA1_Update(&sha1_ctx, purchase_info_bytes, purchase_info_length); CC_SHA1_Final(to_be_verified_data, &sha1_ctx);  SecKeyRef receipt_signing_key = SecTrustCopyPublicKey(trust); __Require(receipt_signing_key, outLabel); __Require_noErr(SecKeyRawVerify(receipt_signing_key, kSecPaddingPKCS1SHA1,                               to_be_verified_data, sizeof(to_be_verified_data),                               signature_blob_ptr->signature, sizeof(signature_blob_ptr->signature)),               outLabel);  /*  Optional:  Verify that the receipt certificate has the 1.2.840.113635.100.6.5.1 Null OID   The signature is a 1024-bit RSA signature.  */  valid = YES;  outLabel:   if (leaf) CFRelease(leaf);   if (intermediate) CFRelease(intermediate);   if (trust) CFRelease(trust);   if (policy) CFRelease(policy);  return valid; } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!