Skip to content

Instantly share code, notes, and snippets.

@tempelmann
Last active April 14, 2019 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tempelmann/904e724163ad9ef56ecba8fb97bd68ec to your computer and use it in GitHub Desktop.
Save tempelmann/904e724163ad9ef56ecba8fb97bd68ec to your computer and use it in GitHub Desktop.
Weird NSUserDefaults/CFPreferences behavior. See https://twitter.com/tempelorg/status/1117388426221846529
i: 165
r0: 165
r1: (null)
r2: 165
r3: (null)
r4: 175
// path contains the full path to the plist file, whereas domain contains just the suite name.
// good
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)path, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)path, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)path, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)path, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)domain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
// bad:
[NSUserDefaults.standardUserDefaults integerForKey:key]; // stuck value
CFPreferencesCopyAppValue((CFStringRef)key, (CFStringRef)path); // stuck value
CFPreferencesCopyAppValue((CFStringRef)key, (CFStringRef)domain); // stuck value
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)domain, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); // stuck value
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)domain, kCFPreferencesAnyUser, kCFPreferencesAnyHost); // null
CFPreferencesCopyValue((CFStringRef)key, (CFStringRef)domain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); // null
// log for the affected app after using:
// sudo log config --subsystem=com.apple.{defaults,cfprefsd} --mode "level:debug, persist:debug"
// and to turn that logging off again:
// sudo log config --subsystem=com.apple.{defaults,cfprefsd} --reset
42.491434 cfprefsd Process 1565 sent a request related to { org.tempel.faf2, user: kCFPreferencesAnyUser, kCFPreferencesCurrentHost, no container, managed: 0 }
42.491514 cfprefsd Process 1565 sent a request related to { org.tempel.faf2, user: tt, kCFPreferencesCurrentHost, no container, managed: 1 }
42.491440 cfprefsd Process 1565 sent a request related to { org.tempel.faf2, user: kCFPreferencesAnyUser, kCFPreferencesCurrentHost, no container, managed: 1 }
42.491516 cfprefsd Process 1565 sent a request related to { kCFPreferencesAnyApplication, user: tt, kCFPreferencesCurrentHost, no container, managed: 1 }
42.491445 cfprefsd Data for { kCFPreferencesAnyApplication, kCFPreferencesAnyUser } was purged due to memory pressure
42.491518 cfprefsd Process 1565 sent a request related to { org.tempel.faf2, user: tt, kCFPreferencesAnyHost, no container, managed: 0 }
42.491487 cfprefsd Couldn't open <private> due to No such file or directory
42.491535 cfprefsd Process 1565 sent a request related to { org.tempel.faf2, user: tt, kCFPreferencesCurrentHost, no container, managed: 0 }
42.491493 cfprefsd Process 1565 sent a request related to { kCFPreferencesAnyApplication, user: kCFPreferencesAnyUser, kCFPreferencesCurrentHost, no container, managed: 0 }
42.491551 cfprefsd Data for { kCFPreferencesAnyApplication, <private> } was purged due to memory pressure
42.491525 cfprefsd no cache for { kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesCurrentHost, no container, managed: 0 }, loading from /Library/Preferences/.GlobalPreferences.plist
42.491551 cfprefsd Data for { kCFPreferencesAnyApplication, <private> } was purged due to memory pressure
42.491577 cfprefsd Process 1565 read data for { kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesCurrentHost, no container, managed: 0 }, backed by /Library/Preferences/.GlobalPreferences.plist
42.491554 cfprefsd Process 1565 read data for { org.tempel.faf2, tt, kCFPreferencesAnyHost, no container, managed: 0 }, backed by /Users/tt/Library/Preferences/org.tempel.faf2.plist
42.491572 cfprefsd Process 1565 read data for { org.tempel.faf2, tt, kCFPreferencesCurrentHost, no container, managed: 0 }, backed by /Users/tt/Library/Preferences/ByHost/org.tempel.faf2.21A029CC-8327-558F-BFB3-EB038C8CE205.plist
42.491581 cfprefsd Process 1565 sent a request related to { kCFPreferencesAnyApplication, user: tt, kCFPreferencesCurrentHost, no container, managed: 0 }
42.491586 cfprefsd Process 1565 sent a request related to { kCFPreferencesAnyApplication, user: tt, kCFPreferencesAnyHost, no container, managed: 0 }
42.491661 cfprefsd no cache for { kCFPreferencesAnyApplication, tt, kCFPreferencesCurrentHost, no container, managed: 0 }, loading from /Users/tt/Library/Preferences/ByHost/.GlobalPreferences.21A029CC-8327-558F-BFB3-EB038C8CE205.plist
42.491728 cfprefsd no cache for { kCFPreferencesAnyApplication, tt, kCFPreferencesAnyHost, no container, managed: 0 }, loading from /Users/tt/Library/Preferences/.GlobalPreferences.plist
42.491820 cfprefsd Process 1565 read data for { kCFPreferencesAnyApplication, tt, kCFPreferencesCurrentHost, no container, managed: 0 }, backed by /Users/tt/Library/Preferences/ByHost/.GlobalPreferences.21A029CC-8327-558F-BFB3-EB038C8CE205.plist
42.491873 cfprefsd Process 1565 read data for { kCFPreferencesAnyApplication, tt, kCFPreferencesAnyHost, no container, managed: 0 }, backed by /Users/tt/Library/Preferences/.GlobalPreferences.plist
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger i = [prefs integerForKey:@"SearchCount"];
[prefs setInteger:i+10 forKey:@"SearchCount"];
NSInteger r0 = [prefs integerForKey:@"SearchCount"];
CFPropertyListRef r1 = CFPreferencesCopyAppValue(CFSTR("SearchCount"), CFSTR("/Users/tt/Library/Preferences/org.tempel.faf2"));
CFPropertyListRef r2 = CFPreferencesCopyAppValue(CFSTR("SearchCount"), CFSTR("org.tempel.faf2")); // same as kCFPreferencesCurrentApplication
CFPropertyListRef r3 = CFPreferencesCopyValue(CFSTR("SearchCount"), CFSTR("/Users/tt/Library/Preferences/org.tempel.faf2"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
system("defaults read org.tempel.faf2 SearchCount >/tmp/r4");
NSString *r4 = [NSString stringWithContentsOfFile:@"/tmp/r4" encoding:NSUTF8StringEncoding error:nil];
NSLog(@"\n%ld\n%ld\n%@\n%@\n%@\n%@", i, r0, r1, r2, r3, r4);
exit(0);
}
@tempelmann
Copy link
Author

tempelmann commented Apr 14, 2019

The output shows three different values. The null values are from the fact that I had previously deleted the prefs using the command defaults delete org.tempel.faf2.

The weird part is that even after setting the value to a different value, it reads back the previous value.

Also, [prefs objectIsForcedForKey:@"SearchCount"] returns false.

It's not possible for me to get rid of the stuck value of 165. I also deleted all occurances of org.tempel.faf2.plist (including in /var/root/Library/Preferences) along with killing cfprefsd, making sure the files do not reappear, and even rebooted into Safe Mode, yet this SearchCount entry persists.

I also checked the global domain, but the key is not in there (e.g. with: defaults read -g | grep "SearchCount"). Even if - rewriting to the app domain should override it.

This problem probably has been caused because I had tried to read and write the app's prefs from a root process, trying various methods, but all using either the defaults command or the CFPreferences API, with various settings to uid, euid, user (root and tt) and with and without the full path to the plist file. At some time, I had thereby also created a separate plist file inside /var/root.

This is on macOS 10.13.6, and the app is not (and never was) sandboxed.

@tempelmann
Copy link
Author

For anyone finding this and looking for a solution: I eventually found a file inside /Users/tempi/Library/Preferences/ByHost that contained all the "stuck" preferences.

I identified this file by using FindAnyFile, looking for any files modified in the past 2 days, and with the File Content containing one of the stuck keys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment