2017-09-14 48 views
8

当升级代码来构建的Xcode 9下,我看到使用requirerequire_noerr编译代码中的错误:Xcode中9投涉及错误 '需要'

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

第一个错误是: error: implicit declaration of function 'require' is invalid in C99

我也得到很多error: use of undeclared identifier 'outLabel'。这是RRTransactionVerifier.m,它是处理接收验证的Apple代码。

如何解决这些错误?

回答

20

requirerequire_noerr是过去在AssertMacros.h中定义的宏。从Xcode 9开始,这些宏已经发生了变化。

的原因都记录在该头文件:

对于远古时代开始,Mac OS X中定义的大多数 宏版本没有__前缀,可以用类似的命名 函数或宏碰撞在用户代码中,包括Boost 和C++标准库中的新功能。

macOS High Sierra和iOS 11现在要求客户端移动到上面定义的 新宏。

如果你想使自己的 项目中使用的宏,你可以通过定义一个Xcode构建配置 __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES宏。请参阅“在Xcode帮助中添加构建配置(xcconfig)文件” 。

因此,要解决该问题,您可以设置定义或更改您的代码以使用新的宏。 require现在是​​,require_noerr现在是__Require_noErr,依此类推。他们在头文件中提供了如何通过脚本更改代码的脚本:

编辑:在脚本第一行的末尾添加一个反斜杠,否则终端会将命令分成两部分。

/* 
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>)" 
*/ 
+1

我跑了转换脚本上面,它的工作完美转换的宏拿到我的项目,以建立在Xcode 9.我想很多人谁使用应用内购买,人们会遇到这个问题。 – codemonkey

+0

我的基于MKStore的应用程序内购买的节省费用!我只是在脚本的第一行添加了一个反斜线以避免终端错误! – Heitor

3

在/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ MacOSX10.11.sdk的/ usr /包含/ AssertMacros.h需要,require_noerr宏现在改性。

请点击此链接:https://github.com/fontforge/fontforge/issues/3164检查更改的列表。 对于你的错误,问题在于这种方法。这是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; 
}