[PR #860] [MERGED] fix(native): keep integral plist reals beyond the JSON range as reals #2297

Closed
opened 2026-10-16 21:16:54 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/860
Author: @kaoru0822-kitauji
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @morluto

Base: main ← Head: fix/plist-integral-reals


📝 Commits (1)

  • 3823f73 fix(native): keep integral plist reals beyond the JSON range as reals

📊 Changes

4 files changed (+199 additions, -65 deletions)

View changed files

📝 src/native/NativeMacOSProvider.ts (+13 -4)
📝 src/native/parsers/plist.test.ts (+59 -4)
📝 src/native/parsers/plist.ts (+122 -56)
📝 tests/boundary/cli/nativePlistCli.test.ts (+5 -1)

📄 Description

Summary

This addresses the Codex P2 on #846 ("Preserve integral plist reals instead of labeling them integers"). It was posted on the final commit after the PR had merged.

plutil -convert json spells an integral <real> the same way as an <integer>. #846 classified any digit-only JSON literal beyond the safe range as an integer, so inspect_plist misreported the element type:

<key>BigReal</key><real>9007199254740992</real>
normalized_result.value.BigReal
main { "$plist_type": "integer", "decimal": "9007199254740992" } plus "1 integer value(s) exceed…"
this PR 9007199254740992 (a real, decoded exactly), no limitation

(Confirmed with real plutil on macOS: plutil -convert json prints "BigReal":9007199254740992.)

Fix

  • plistJsonNeedsNumberTypes(json) reports whether plutil's JSON holds an integral number literal beyond the exact range. Only then does the provider also run plutil -convert xml1. Ordinary plists still use one plutil invocation, and the extra invocation is recorded in provenance.

  • parsePlistJson(json, xml) keeps exact digits from the JSON source and takes the element type from the XML literals:

    • an <integer> with those exact digits and no <real> decoding to the same number → { "$plist_type": "integer", "decimal": "<digits>" };
    • a <real> and no matching <integer> → the decoded number;
    • otherwise the type is reported as decoded, with the existing explicit limitation that the <integer>/<real> origin cannot be identified.

    Without XML literals, such a number is never labeled an integer. JSON keeps per-literal digits, so two integers that round to the same double, such as 9007199254740993 and 9007199254740992, both stay exact. The XML-only path reports that case as ambiguous.

  • The XML fallback (data/dates/non-finite reals) is unchanged. It now shares the literal reader and limitation text.

No schema change. docs:check passes without regeneration.

Verification

  • src/native/parsers/plist.test.ts covers exact integers including the …992/…993 pair, integral JSON reals, ambiguous and no-XML cases, and the predicate (9/9).
  • The real-plutil CLI test tests/boundary/cli/nativePlistCli.test.ts now includes <real>9007199254740992</real> and <real>1e20</real> in both the JSON (data: false) and XML (data: true) paths. The JSON case fails on main and passes here. The suite passes 7/7, and nativeProvider.test.ts passes.
  • Manual node scripts/rea.mjs inspect-plist X.app --relative-path Contents/R.plist --json on macOS arm64 with mixed integers and reals: the provenance shows file, plutil -convert json, and plutil -convert xml1, and the types are as described above.
  • npm run check:changed (4 files / 20 tests), npm run check:fast, and npm run docs:check passed.

No Hopper/Ghidra/IDA verification is needed (native plutil inspection only).

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/860 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/plist-integral-reals` --- ### 📝 Commits (1) - [`3823f73`](https://github.com/morluto/rea/commit/3823f73620cdcf28033e41a886dc7213f5bc565a) fix(native): keep integral plist reals beyond the JSON range as reals ### 📊 Changes **4 files changed** (+199 additions, -65 deletions) <details> <summary>View changed files</summary> 📝 `src/native/NativeMacOSProvider.ts` (+13 -4) 📝 `src/native/parsers/plist.test.ts` (+59 -4) 📝 `src/native/parsers/plist.ts` (+122 -56) 📝 `tests/boundary/cli/nativePlistCli.test.ts` (+5 -1) </details> ### 📄 Description ## Summary This addresses the Codex P2 on #846 (["Preserve integral plist reals instead of labeling them integers"](https://github.com/morluto/rea/pull/846)). It was posted on the final commit after the PR had merged. `plutil -convert json` spells an integral `<real>` the same way as an `<integer>`. #846 classified any digit-only JSON literal beyond the safe range as an integer, so `inspect_plist` misreported the element type: ```text <key>BigReal</key><real>9007199254740992</real> ``` | | `normalized_result.value.BigReal` | |---|---| | `main` | `{ "$plist_type": "integer", "decimal": "9007199254740992" }` plus "1 integer value(s) exceed…" | | this PR | `9007199254740992` (a real, decoded exactly), no limitation | (Confirmed with real `plutil` on macOS: `plutil -convert json` prints `"BigReal":9007199254740992`.) ## Fix - `plistJsonNeedsNumberTypes(json)` reports whether plutil's JSON holds an integral number literal beyond the exact range. Only then does the provider also run `plutil -convert xml1`. Ordinary plists still use one plutil invocation, and the extra invocation is recorded in `provenance`. - `parsePlistJson(json, xml)` keeps exact digits from the JSON source and takes the element type from the XML literals: - an `<integer>` with those exact digits and no `<real>` decoding to the same number → `{ "$plist_type": "integer", "decimal": "<digits>" }`; - a `<real>` and no matching `<integer>` → the decoded number; - otherwise the type is reported as decoded, with the existing explicit limitation that the `<integer>`/`<real>` origin cannot be identified. Without XML literals, such a number is never labeled an integer. JSON keeps per-literal digits, so two integers that round to the same double, such as `9007199254740993` and `9007199254740992`, both stay exact. The XML-only path reports that case as ambiguous. - The XML fallback (data/dates/non-finite reals) is unchanged. It now shares the literal reader and limitation text. No schema change. `docs:check` passes without regeneration. ## Verification - `src/native/parsers/plist.test.ts` covers exact integers including the `…992`/`…993` pair, integral JSON reals, ambiguous and no-XML cases, and the predicate (9/9). - The real-`plutil` CLI test `tests/boundary/cli/nativePlistCli.test.ts` now includes `<real>9007199254740992</real>` and `<real>1e20</real>` in both the JSON (`data: false`) and XML (`data: true`) paths. **The JSON case fails on `main` and passes here.** The suite passes 7/7, and `nativeProvider.test.ts` passes. - Manual `node scripts/rea.mjs inspect-plist X.app --relative-path Contents/R.plist --json` on macOS arm64 with mixed integers and reals: the provenance shows `file`, `plutil -convert json`, and `plutil -convert xml1`, and the types are as described above. - `npm run check:changed` (4 files / 20 tests), `npm run check:fast`, and `npm run docs:check` passed. No Hopper/Ghidra/IDA verification is needed (native `plutil` inspection only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-16 21:16:54 +00:00
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#2297
No description provided.