Crash in SecItemCopyMatching under C++

I'm extending a C++ library to gather some data from the keychain, I have a prototype code written in Swift that works just fine:

import Security;
import Foundation;

let query: [String: Any] = [
    kSecClass as String: kSecClassCertificate,
    kSecReturnData as String: true,
    kSecMatchLimit as String: kSecMatchLimitAll
]
var items: CFTypeRef?;
let status = SecItemCopyMatching(query as CFDictionary, &items);

However trying to do the same in C++ crashes:

#include <security/SecItem.h>
int main() {
    static const void* keys[] = {
        kSecClass,
        kSecMatchLimit,
        kSecReturnData,
    };
    static const void* values[] = {
        kSecClassCertificate,
        kSecMatchLimitOne,
        kCFBooleanTrue,
    };
    static_assert(sizeof(keys) == sizeof(values), "Key-value lengths mismatch for query dictionary constructor!");
    CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys), nullptr, nullptr);
    SecItemCopyMatching(query, nullptr);
    return 0;
}

With the backtrace of:

Thread 1 Queue : com.apple.main-thread (serial)
#0	0x0000000191a7f1b8 in objc_retain ()
#1	0x0000000191ed9e0c in -[__NSDictionaryM __setObject:forKey:] ()
#2	0x0000000191f3ae28 in __CFDictionaryApplyFunction_block_invoke ()
#3	0x0000000191effbb0 in CFBasicHashApply ()
#4	0x0000000191ef2ccc in CFDictionaryApplyFunction ()
#5	0x0000000194cdafc4 in SecCFDictionaryCOWGetMutable ()
#6	0x0000000194cdf3e8 in SecItemCopyMatching_ios ()
#7	0x0000000194e79754 in SecItemCopyMatching ()
#8	0x0000000100003f68 in main at /Users/kkurek/whatever/whatever/main.cpp:15
#9	0x0000000191acf154 in start ()

I don't have much experience with MacOS so I'm not sure how to analyze this situation. I have tried running with sanitizers enabled but somehow the crash doesn't occur at all when running with them.

Answered by endecotp in 815649022

sizeof(x) returns the size of x in bytes, not the number of elements in the array.

Accepted Answer

sizeof(x) returns the size of x in bytes, not the number of elements in the array.

Just FYI:

// C++ function to return the number of elements in a C array.  Usage:
// sometype X[231];
// assert(elemsof(X)==231);

template <typename T, size_t N>
constexpr inline size_t elemsof(const T (&) [N]) {
  return N;
}
Crash in SecItemCopyMatching under C++
 
 
Q