DF-2226 / prop_empty_key.c
/* DF-2226: prop_dictionary internalizer accepts an empty <key></key>, * violating the keysym non-empty invariant that _prop_dict_keysym_externalize * asserts (_PROP_ASSERT(pdk->pdk_key[0] != '\0'), prop_dictionary.c:248). * DFly libprop internalize wants a <plist> wrapper; same code is compiled * into the kernel (sys/libprop is shared with lib/libprop). */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libprop/proplib.h> static const char *GOOD_KEY_XML = "<plist version=\"1.0\"><dict><key>ok</key><string>x</string></dict></plist>"; static const char *EMPTY_KEY_XML = "<plist version=\"1.0\"><dict><key></key><string>x</string></dict></plist>"; int main(void) { prop_dictionary_t d; prop_object_t v; char *xml; printf("[*] control: internalize GOOD key: "); d = prop_dictionary_internalize(GOOD_KEY_XML); printf("%s (expected)\n", d ? "accepted" : "REJECTED"); if (d) prop_object_release(d); printf("[*] internalize EMPTY key: "); d = prop_dictionary_internalize(EMPTY_KEY_XML); printf("%s <-- invariant violated if accepted\n", d ? "ACCEPTED" : "rejected"); if (d == NULL) { printf("[-] not reproduced\n"); return 1; } v = prop_dictionary_get(d, ""); printf("[%c] prop_dictionary_get(dict, \"\") = %p (empty keysym interned in tree)\n", v ? '+' : '-', (void *)v); printf("[*] prop_dictionary_externalize() of the empty-key dict\n"); printf(" (externalize asserts pdk_key[0] != 0 -- userland assert/abort,\n"); printf(" kernel INVARIANTS panic)\n"); fflush(stdout); xml = prop_dictionary_externalize(d); printf("[*] externalize returned %p\n", (void *)xml); if (xml) free(xml); return 0; } |