2017-09-14 24 views
8

Khi nâng cấp mã để xây dựng dưới Xcode 9, tôi thấy biên dịch lỗi trong mã sử dụng requirerequire_noerr:Xcode 9 ném lỗi liên quan đến 'đòi hỏi'

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

Lỗi đầu tiên là: error: implicit declaration of function 'require' is invalid in C99

tôi cũng nhận được rất nhiều error: use of undeclared identifier 'outLabel'. Đây là trong RRTransactionVerifier.m là mã của Apple để xử lý xác nhận nhận.

Làm cách nào để sửa các lỗi này?

Trả lời

20

requirerequire_noerr là các macro được sử dụng để xác định trong AssertMacros.h. Kể từ Xcode 9, các macro này đã thay đổi.

Những lý do được diễn tả trong tập tin tiêu đề:

Đối với thời xa xưa, Mac OS X đã xác định phiên bản của hầu hết các macro mà không __ tiền tố, có thể va chạm với tên tương tự chức năng hoặc macro trong mã người dùng, bao gồm chức năng mới trong Boost và thư viện chuẩn C++.

macOS Cao Sierra và iOS 11 giờ sẽ yêu cầu khách hàng chuyển sang các macro mới như được định nghĩa ở trên.

Nếu bạn muốn bật macro để sử dụng trong dự án của riêng mình, bạn có thể xác định macro __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES qua cấu hình Xcode Build. Xem "Thêm tệp cấu hình xây dựng (xcconfig)" trong Trợ giúp Xcode.

Vì vậy, để khắc phục vấn đề bạn có thể đặt xác định hoặc thay đổi mã của bạn để sử dụng các macro mới. require hiện là __Require, require_noerr hiện là __Require_noErr, v.v. Chúng cung cấp một tập lệnh trong tệp tiêu đề về cách thay đổi mã của bạn thông qua tập lệnh:

EDIT: Đã thêm một dấu gạch chéo ngược vào cuối dòng đầu tiên của tập lệnh, nếu không Trình kết nối sẽ ngắt lệnh thành hai.

/* 
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

Tôi đã chạy tập lệnh chuyển đổi ở trên và nó hoạt động hoàn hảo để chuyển đổi macro và nhận dự án của tôi để xây dựng trong xcode 9. Tôi nghĩ rằng rất nhiều người sử dụng Mua trong ứng dụng sẽ gặp sự cố này. – codemonkey

+0

Trình tiết kiệm điện cho các giao dịch mua trong ứng dụng dựa trên MKStore của tôi !! Tôi vừa thêm dấu gạch chéo ngược vào dòng đầu tiên của tập lệnh để tránh lỗi thiết bị đầu cuối! – Heitor

3

Trong /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ MacOSX10.11.sdk/usr/include/AssertMacros.h yêu cầu, macro require_noerr được sửa đổi tại .

Làm theo liên kết sau: https://github.com/fontforge/fontforge/issues/3164 để kiểm tra danh sách đã thay đổi. Đối với lỗi của bạn, vấn đề là trong phương pháp này. Đây là phương pháp được sửa đổi trong 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; 
} 
Các vấn đề liên quan