升级代码以在Xcode 9下构建时,我在使用require
和require_noerr
的代码中看到编译错误:
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代码。
如何修复这些错误?
答案 0 :(得分:22)
require
和require_noerr
是以前在AssertMacros.h中定义的宏。从Xcode 9开始,这些宏发生了变化。
原因记录在该头文件中:
对于远古时代,Mac OS X已经定义了大部分版本 没有__前缀的宏,它可能与类似名称冲突 用户代码中的函数或宏,包括Boost中的新功能 和C ++标准库。
macOS High Sierra和iOS 11现在要求客户转移到 如上定义的新宏。
如果您想在自己的内部启用宏 项目,你可以定义 通过Xcode构建配置__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES宏。请参阅"添加构建配置(xcconfig)文件" 在Xcode帮助中。
因此,要解决此问题,您可以设置定义或更改代码以使用新宏。
require
现在是__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 :(得分:3)
在/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ MacOSX10.11.sdk / usr / include / 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;
}