NSProcessInfo operatingSystemVersion generates warning CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary

Consider this very trivial code which accesses the operatingSystemVersion property of NSProcessInfo as documented at https://developer.apple.com/documentation/foundation/nsprocessinfo/1410906-operatingsystemversion

osversion.c:

#include <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
    NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
    fprintf(stderr, "OS version: %ld.%ld.%ld\n", osVersion.majorVersion, osVersion.minorVersion, osVersion.patchVersion);
}

Compile it:

/usr/bin/clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/System/Library/Frameworks -x objective-c -o a.out -framework Foundation osversion.c

Then run it:

./a.out

It works fine and prints the OS version:

OS version: 14.6.1

Run it again and pass it some arbitrary program arguments:

./a.out foo bar

Still continues to work fine and prints the output:

OS version: 14.6.1

Now run it again and this time pass it two program arguments, the first one being - and the second one being something of the form {x=y}

./a.out - {x=y}

This time notice how it prints a couple of warning logs from CFPropertyListCreateFromXMLData before printing the output:

2024-10-11 11:18:03.584 a.out[61327:32412190] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
2024-10-11 11:18:03.585 a.out[61327:32412190] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
OS version: 14.6.1

As far as I can see there's nothing wrong in the code nor the user inputs to the program. Is this some issue in the internal implementation of NSProcessInfo? Should this be reported as an issue through feedback assistant (which category)?

Although this example was run on 14.6.1 of macos, the issue is reproducible on older versions too.

Answered by DTS Engineer in 808847022
Should this be reported as an issue through feedback assistant … ?

No.

Well, you can report it as log noise if you like, but it’s definitely not a sign of an actual problem.

Foundation was created as part of Apple’s (well, NeXT’s) app development story. For this reason it contains a component, UserDefaults, with some helpful, but non-obvious, behaviour: You can override specific user defaults by passing them on the command line. For example, consider this program:

import Foundation

func main() {
    print(UserDefaults.standard.string(forKey: "QTest") ?? "-")
}

main()

If you run it with no arguments it gets nil back for this default:

% ./Test766100
-

But you can supply a default as an argument:

% ./Test766100 -QTest 'Hello Cruel World!'
Hello Cruel World!

This mechanism supports all property list types. That’s super useful in some cases. For an example of that, check out this post.

This log message is being triggered by the property list parser seeing what it thinks is an old school property list and failing to parse it. That’s not a big deal. It just means that the result value isn’t going to get set it UserDefaults.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer
Should this be reported as an issue through feedback assistant … ?

No.

Well, you can report it as log noise if you like, but it’s definitely not a sign of an actual problem.

Foundation was created as part of Apple’s (well, NeXT’s) app development story. For this reason it contains a component, UserDefaults, with some helpful, but non-obvious, behaviour: You can override specific user defaults by passing them on the command line. For example, consider this program:

import Foundation

func main() {
    print(UserDefaults.standard.string(forKey: "QTest") ?? "-")
}

main()

If you run it with no arguments it gets nil back for this default:

% ./Test766100
-

But you can supply a default as an argument:

% ./Test766100 -QTest 'Hello Cruel World!'
Hello Cruel World!

This mechanism supports all property list types. That’s super useful in some cases. For an example of that, check out this post.

This log message is being triggered by the property list parser seeing what it thinks is an old school property list and failing to parse it. That’s not a big deal. It just means that the result value isn’t going to get set it UserDefaults.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you Quinn for that explanation and the example. That helps.

Foundation was created as part of Apple’s (well, NeXT’s) app development story. For this reason it contains a component, UserDefaults, with some helpful, but non-obvious, behaviour: You can override specific user defaults by passing them on the command line.

More out of curiosity - for a property like NSProcessInfo's operatingSystemVersion, which I guess will always be fixed on a given host, does it still internally need/use any user overriddable values that require parsing the command line of a process?

Apple’s frameworks tend to use lazy initialisation, so that fact that you’re seeing this message indicates that someone called upon the user defaults subsystem. Fortunately there’s an easy way to see what that was: Set a breakpoint on _CFPropertyListMissingSemicolon, just like that log message says:

% ./Test766100 - '{x=y}'
2024-10-15 08:29:52.210 Test766100[17986:1896989] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
2024-10-15 08:29:52.211 Test766100[17986:1896989] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
OS version: 14.7.0
% lldb Test766100
(lldb) target create "Test766100"
Current executable set to '/Users/quinn/Library/Developer/Xcode/DerivedData/Test766100-eqgrugnuouzcamctylmfxiicxmtz/Build/Products/Debug/Test766100' (arm64).
(lldb) br set -n _CFPropertyListMissingSemicolon
Breakpoint 2: where = CoreFoundation`_CFPropertyListMissingSemicolon, address = 0x0000000184f97df4
(lldb) r
Process 17998 launched: '/Users/quinn/Library/Developer/Xcode/DerivedData/Test766100-eqgrugnuouzcamctylmfxiicxmtz/Build/Products/Debug/Test766100' (arm64)
Process 17998 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x0000000184f97df4 CoreFoundation`_CFPropertyListMissingSemicolon
CoreFoundation`_CFPropertyListMissingSemicolon:
->  0x184f97df4 <+0>:  pacibsp 
    0x184f97df8 <+4>:  sub    sp, sp, #0x20
    0x184f97dfc <+8>:  stp    x29, x30, [sp, #0x10]
    0x184f97e00 <+12>: add    x29, sp, #0x10
Target 0: (Test766100) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  * frame #0:  … CoreFoundation`_CFPropertyListMissingSemicolon
    frame #1:  … CoreFoundation`parsePlistDictContent + 356
    frame #2:  … CoreFoundation`parsePlistObject + 256
    frame #3:  … CoreFoundation`__CFCreateOldStylePropertyListOrStringsFile + 556
    frame #4:  … CoreFoundation`_CFPropertyListCreateFromUTF8Data + 1064
    frame #5:  … CoreFoundation`_CFPropertyListCreateFromXMLStringError + 140
    frame #6:  … CoreFoundation`_CFPropertyListCreateFromXMLString + 68
    frame #7:  … CoreFoundation`__getDefaultArguments_block_invoke + 340
    frame #8:  … libdispatch.dylib`_dispatch_client_callout + 20
    frame #9:  … libdispatch.dylib`_dispatch_once_callout + 32
    frame #10: … CoreFoundation`_addBackstopValuesForIdentifierAndSource + 652
    frame #11: … CoreFoundation`__81-[_CFXPreferences(SourceAdditions) withNamedVolatileSourceForIdentifier:perform:]_block_invoke + 144
    frame #12: … CoreFoundation`-[_CFXPreferences withNamedVolatileSourceForIdentifier:perform:] + 272
    frame #13: … CoreFoundation`-[CFPrefsSearchListSource addNamedVolatileSourceForIdentifier:] + 136
    frame #14: … CoreFoundation`__108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke.155 + 296
    frame #15: … CoreFoundation`-[_CFXPreferences withSearchLists:] + 84
    frame #16: … CoreFoundation`__108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke + 300
    frame #17: … CoreFoundation`-[_CFXPreferences withSearchListForIdentifier:container:cloudConfigurationURL:perform:] + 440
    frame #18: … CoreFoundation`-[_CFXPreferences copyAppValueForKey:identifier:container:configurationURL:] + 156
    frame #19: … CoreFoundation`_CFPreferencesCopyAppValueWithContainerAndConfiguration + 112
    frame #20: … CoreFoundation`_CFBundleCopyUserLanguages + 72
    frame #21: … CoreFoundation`_CFBundleCopyLanguageSearchListInBundle + 80
    frame #22: … CoreFoundation`_copyQueryTable + 64
    frame #23: … CoreFoundation`_copyResourceURLsFromBundle + 376
    frame #24: … CoreFoundation`_CFBundleCopyFindResources + 1400
    frame #25: … CoreFoundation`CFBundleCopyResourceURL + 56
    frame #26: … CoreFoundation`_CFBundleGetStringsSources + 304
    frame #27: … CoreFoundation`_copyStringTable + 612
    frame #28: … CoreFoundation`_CFBundleCopyLocalizedStringForLocalizationTableURLAndMarkdownOption + 204
    frame #29: … CoreFoundation`_CFCopyLocalizedVersionKey + 196
    frame #30: … CoreFoundation`_CFCopyVersionDictionary + 196
    frame #31: … CoreFoundation`___CFCopySystemVersionDictionary_block_invoke + 48
    frame #32: … libdispatch.dylib`_dispatch_client_callout + 20
    frame #33: … libdispatch.dylib`_dispatch_once_callout + 32
    frame #34: … CoreFoundation`_CFCopySystemVersionDictionary + 92
    frame #35: … CoreFoundation`_CFCopySystemVersionDictionaryValue + 36
    frame #36: … CoreFoundation`___CFOperatingSystemVersionGetCurrent_block_invoke + 56
    frame #37: … libdispatch.dylib`_dispatch_client_callout + 20
    frame #38: … libdispatch.dylib`_dispatch_once_callout + 32
    frame #39: … CoreFoundation`_CFOperatingSystemVersionGetCurrent + 92
    frame #40: … Foundation`-[NSProcessInfo operatingSystemVersion] + 56
    frame #41: … Test766100`main(argc=3, argv=0x000000016fdff3e8) at main.m:6:42
    frame #42: … dyld`start + 2476
(lldb) 

So, Foundation calls upon Core Foundation (frame 39) which invokes the CFBundle machinery (frame 28). CFBundle needs to know about the user’s preferred languages (frame 20) which is something that’s set via a user default.


Taking a big step back, the standard way to get the macOS version from the command line is to read SystemVersion.plist:

% /usr/libexec/PlistBuddy -c "Print ProductVersion" /System/Library/CoreServices/SystemVersion.plist
14.7

This is an exception to the general rule that you shouldn’t hard code paths; that path has to continue to exist so that old versions of macOS can correctly identify new versions.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hello Quinn,

Apple’s frameworks tend to use lazy initialisation, ...

Thank you for that detail. That (and the rest of what you note in your answer) addresses my curiosity.

Taking a big step back, the standard way to get the macOS version from the command line

Noted. Although in the context of where this issue shows up, the command line way of determining the OS version isn't applicable for us. For context, this unexpected log message got reported as a bug against the JDK https://bugs.openjdk.org/browse/JDK-8340727. The JDK internally uses the NSProcessInfo's operationSystemProperty to determine the OS version, which then triggers the log.

Well, you can report it as log noise if you like, but it’s definitely not a sign of an actual problem.

Later today I will go ahead and report this, through feedback assistant, as a log noise.

Thank you for your answers and the detailed technical explanations.

Later today I will go ahead and report this, through feedback assistant, as a log noise.

I've filed FB15498510 suggesting this log message be suppressed.

NSProcessInfo operatingSystemVersion generates warning CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary
 
 
Q