[GH-ISSUE #4906] [Bug] XML plist reals spelled +infinity, -infinity or nan are reported as unknown reals #3045

Closed
opened 2026-10-31 00:35:24 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @mertkayacs on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4906

Before submitting

  • Searched open and closed reports (PR and issue searches for infinity, non-finite real, nan: #841, #4789, #4295, #4852 and PR #4047 cover neighbouring behavior, none this one).
  • Removed credentials and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

inspect-keyed-archive (CLI and the inspect_keyed_archive MCP tool) and the XML fallback of inspect_plist report every <real> whose text is one of CFPropertyList's non-finite spellings as an unknown real. For an XML keyed archive whose $objects holds <real>+infinity</real>, <real>-infinity</real> and <real>nan</real>, each object comes back as { "kind": "scalar", "status": "observed", "value": { "$plist_type": "real", "value": null } }, and the limitations contain 3 non-finite real value(s) are reported as { "$plist_type": "real", "value": null } because JSON evidence cannot preserve NaN vs infinity. The sign and the identity of each value are lost even though the source text states them.

Reproduction

  1. Save the archive below as non_finite.plist.
  2. rea inspect-keyed-archive /absolute/path/non_finite.plist --json
  3. Read normalized_result.objects[1..3].value and normalized_result.limitations.
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0"><dict><key>$archiver</key><string>NSKeyedArchiver</string><key>$version</key><integer>100000</integer><key>$objects</key><array><string>$null</string><real>+infinity</real><real>-infinity</real><real>nan</real></array><key>$top</key><dict><key>up</key><dict><key>CF$UID</key><integer>1</integer></dict><key>down</key><dict><key>CF$UID</key><integer>2</integer></dict><key>missing</key><dict><key>CF$UID</key><integer>3</integer></dict></dict></dict></plist>

Reproduced through the repository's public CLI and MCP acceptance harness (npm run test:focused -- tests/acceptance/applications/keyedArchiveScalarKinds.test.ts with the regression case from the linked PR): fails on main 2fb5e204a every time, 2 of 2 runs.

Expected behavior

The three values are observed, so they should be reported with their sign and spelling, for example { "$plist_type": "real", "value": "-infinity" }, the same way a negative-zero real is reported as { "$plist_type": "real", "value": "-0" }. CFPropertyList's XML writer emits exactly nan, +infinity and -infinity for non-finite doubles (__CFNumberCreateFormattingDescriptionAsFloat64 in CFNumber.c, used by the plist writer), and its parser accepts nan, +infinity, -infinity, infinity, -inf, inf and +inf case-insensitively (parseRealTag in CFPropertyList.c, swift-corelibs-foundation main). value: null should stay reserved for non-finite numbers that carry no spelling.

Impact and scope

Evidence integrity: an exact observed value is replaced by an unknown, and the limitation text claims an inability the decoder does not have. Affects any XML plist or keyed archive written by Foundation with a non-finite real. Frequency in real targets: NOT_ENOUGH_INFO; not measured. Binary plists are a separate case (the double carries no spelling) and are not covered by this report.

REA version

6.5.0, source 2fb5e204a

Runtime and platform

Node 24.18.0; Linux x64

Target and artifact context

XML property list (NSKeyedArchiver archive) written by hand from the CFPropertyList spellings; no provider involved.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Executed: the acceptance case above fails on main with objects[1].value equal to { "$plist_type": "real", "value": null } where "+infinity" is expected. Source-derived: src/domain/propertyListXml.ts decodes <real> with Number.parseFloat(literal.text), which recognises only JavaScript's case-sensitive Infinity, so +infinity, -infinity and nan all parse to NaN; src/domain/apple/plistValue.ts then reports every non-finite number as value: null. A <real>Infinity</real> written by plist@5 is the one spelling that survives parseFloat, and it is still reported as null by the projection.

Typed outcome or recovery expected

{ "$plist_type": "real", "value": "+infinity" | "-infinity" | "nan" } with status: observed, counted in a limitation that names the spellings; value: null only for non-finite numbers without a spelling.

Analysis or suspected cause

Source-derived, see above. I have a fix with regression tests ready and will link the PR.

Originally created by @mertkayacs on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4906 ### Before submitting - [x] Searched open and closed reports (PR and issue searches for infinity, non-finite real, nan: #841, #4789, #4295, #4852 and PR #4047 cover neighbouring behavior, none this one). - [x] Removed credentials and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior `inspect-keyed-archive` (CLI and the `inspect_keyed_archive` MCP tool) and the XML fallback of `inspect_plist` report every `<real>` whose text is one of CFPropertyList's non-finite spellings as an unknown real. For an XML keyed archive whose `$objects` holds `<real>+infinity</real>`, `<real>-infinity</real>` and `<real>nan</real>`, each object comes back as `{ "kind": "scalar", "status": "observed", "value": { "$plist_type": "real", "value": null } }`, and the limitations contain `3 non-finite real value(s) are reported as { "$plist_type": "real", "value": null } because JSON evidence cannot preserve NaN vs infinity.` The sign and the identity of each value are lost even though the source text states them. ### Reproduction 1. Save the archive below as `non_finite.plist`. 2. `rea inspect-keyed-archive /absolute/path/non_finite.plist --json` 3. Read `normalized_result.objects[1..3].value` and `normalized_result.limitations`. ```xml <?xml version="1.0" encoding="UTF-8"?> <plist version="1.0"><dict><key>$archiver</key><string>NSKeyedArchiver</string><key>$version</key><integer>100000</integer><key>$objects</key><array><string>$null</string><real>+infinity</real><real>-infinity</real><real>nan</real></array><key>$top</key><dict><key>up</key><dict><key>CF$UID</key><integer>1</integer></dict><key>down</key><dict><key>CF$UID</key><integer>2</integer></dict><key>missing</key><dict><key>CF$UID</key><integer>3</integer></dict></dict></dict></plist> ``` Reproduced through the repository's public CLI and MCP acceptance harness (`npm run test:focused -- tests/acceptance/applications/keyedArchiveScalarKinds.test.ts` with the regression case from the linked PR): fails on main `2fb5e204a` every time, 2 of 2 runs. ### Expected behavior The three values are observed, so they should be reported with their sign and spelling, for example `{ "$plist_type": "real", "value": "-infinity" }`, the same way a negative-zero real is reported as `{ "$plist_type": "real", "value": "-0" }`. CFPropertyList's XML writer emits exactly `nan`, `+infinity` and `-infinity` for non-finite doubles (`__CFNumberCreateFormattingDescriptionAsFloat64` in CFNumber.c, used by the plist writer), and its parser accepts `nan`, `+infinity`, `-infinity`, `infinity`, `-inf`, `inf` and `+inf` case-insensitively (`parseRealTag` in CFPropertyList.c, swift-corelibs-foundation main). `value: null` should stay reserved for non-finite numbers that carry no spelling. ### Impact and scope Evidence integrity: an exact observed value is replaced by an unknown, and the limitation text claims an inability the decoder does not have. Affects any XML plist or keyed archive written by Foundation with a non-finite real. Frequency in real targets: NOT_ENOUGH_INFO; not measured. Binary plists are a separate case (the double carries no spelling) and are not covered by this report. ### REA version 6.5.0, source 2fb5e204a ### Runtime and platform Node 24.18.0; Linux x64 ### Target and artifact context XML property list (NSKeyedArchiver archive) written by hand from the CFPropertyList spellings; no provider involved. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Executed: the acceptance case above fails on main with `objects[1].value` equal to `{ "$plist_type": "real", "value": null }` where `"+infinity"` is expected. Source-derived: `src/domain/propertyListXml.ts` decodes `<real>` with `Number.parseFloat(literal.text)`, which recognises only JavaScript's case-sensitive `Infinity`, so `+infinity`, `-infinity` and `nan` all parse to NaN; `src/domain/apple/plistValue.ts` then reports every non-finite number as `value: null`. A `<real>Infinity</real>` written by `plist@5` is the one spelling that survives `parseFloat`, and it is still reported as `null` by the projection. ### Typed outcome or recovery expected `{ "$plist_type": "real", "value": "+infinity" | "-infinity" | "nan" }` with `status: observed`, counted in a limitation that names the spellings; `value: null` only for non-finite numbers without a spelling. ### Analysis or suspected cause Source-derived, see above. I have a fix with regression tests ready and will link the PR.
Author
Owner

@mertkayacs commented on GitHub (Oct 17, 2026):

Fix with regression tests: https://github.com/morluto/rea/pull/4908. The XML decoder now reads CFPropertyList's spellings (nan, +infinity, -infinity, and the parser's infinity/inf forms, case-insensitively) before parseFloat and reports them as observed values; unspelled non-finite numbers keep value: null.

<!-- gh-comment-id:6242902382 --> @mertkayacs commented on GitHub (Oct 17, 2026): Fix with regression tests: https://github.com/morluto/rea/pull/4908. The XML decoder now reads CFPropertyList's spellings (nan, +infinity, -infinity, and the parser's infinity/inf forms, case-insensitively) before parseFloat and reports them as observed values; unspelled non-finite numbers keep value: null.
Author
Owner

@morluto commented on GitHub (Oct 17, 2026):

Fixed on main in 6c9870879 (shared XML parser/projection, documentation, public CLI/MCP regressions) and 69324b0f8 (missed entitlement consumer). Adapted @mertkayacs's PR #4908 with coauthor credit.

The XML owner recognizes completely observed CFPropertyList non-finite literals. Typed scalars preserve NaN and signed infinity through key filtering, JSON projection and keyed-archive classification; lookalike dictionaries remain dictionaries. Aliases/case normalize to canonical writer spellings, explicitly documented. Unsupported markup stays on the preexisting compatibility fallback with incomplete metadata. Token recognition checks the actual supported length before lowercasing. The native entitlement decoder now consumes shared value/number projections and carries their limitations rather than treating decoded scalar instances as JSON dictionaries.

Executed on macOS26.3 arm64 / Node24.18:

  • Public CLI/MCP acceptance baseline: 2 failures,4 controls passed.
  • Controlled entitlement response baseline: 1 failure,29 controls passed.
  • Final focused selection: 430 passed across25files, including public keyed-archive CLI/MCP, real plutil CLI conversion, real signature CLI controls and provider lifecycle regressions.
  • check:fast, docs:check (5), discovery (1563 files exactly once), normal commit/pre-push hooks. Two read-only source reviews found no remaining blocker after corrections.
  • Actual plutil lint/XML conversion accepted all11 tested canonical/alias/case/CDATA literals and rejected the3 unsupported textual controls; source bytes unchanged. Numeric overflow and finite controls were also examined.

Research: CFPropertyList parseRealTag source and DeepWiki context were compared with native observations: https://github.com/swiftlang/swift-corelibs-foundation/blob/main/Sources/CoreFoundation/CFPropertyList.c#L1709

Limits: codesign/AMFI rejected an authored non-finite entitlement before inspection; its regression uses controlled command output, not a real signing reproduction. No Linux/Windows run here. Direct binary decoding still discards known IEEE value identity, separately reproduced through public CLI and tracked in #4919; native plutil XML conversion recovers it. Strict malformed-literal policy remains #4852. No performance or full-codebase completion claim. Heavy CPU test/profiling remain stopped.

<!-- gh-comment-id:6243340007 --> @morluto commented on GitHub (Oct 17, 2026): Fixed on main in 6c9870879 (shared XML parser/projection, documentation, public CLI/MCP regressions) and 69324b0f8 (missed entitlement consumer). Adapted @mertkayacs's PR #4908 with coauthor credit. The XML owner recognizes completely observed CFPropertyList non-finite literals. Typed scalars preserve NaN and signed infinity through key filtering, JSON projection and keyed-archive classification; lookalike dictionaries remain dictionaries. Aliases/case normalize to canonical writer spellings, explicitly documented. Unsupported markup stays on the preexisting compatibility fallback with incomplete metadata. Token recognition checks the actual supported length before lowercasing. The native entitlement decoder now consumes shared value/number projections and carries their limitations rather than treating decoded scalar instances as JSON dictionaries. Executed on macOS26.3 arm64 / Node24.18: - Public CLI/MCP acceptance baseline: 2 failures,4 controls passed. - Controlled entitlement response baseline: 1 failure,29 controls passed. - Final focused selection: 430 passed across25files, including public keyed-archive CLI/MCP, real plutil CLI conversion, real signature CLI controls and provider lifecycle regressions. - check:fast, docs:check (5), discovery (1563 files exactly once), normal commit/pre-push hooks. Two read-only source reviews found no remaining blocker after corrections. - Actual plutil lint/XML conversion accepted all11 tested canonical/alias/case/CDATA literals and rejected the3 unsupported textual controls; source bytes unchanged. Numeric overflow and finite controls were also examined. Research: CFPropertyList parseRealTag source and DeepWiki context were compared with native observations: https://github.com/swiftlang/swift-corelibs-foundation/blob/main/Sources/CoreFoundation/CFPropertyList.c#L1709 Limits: codesign/AMFI rejected an authored non-finite entitlement before inspection; its regression uses controlled command output, not a real signing reproduction. No Linux/Windows run here. Direct binary decoding still discards known IEEE value identity, separately reproduced through public CLI and tracked in #4919; native plutil XML conversion recovers it. Strict malformed-literal policy remains #4852. No performance or full-codebase completion claim. Heavy CPU test/profiling remain stopped.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3045
No description provided.