2017-09-14 64 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; 
}