[GH-ISSUE #6807] [Bug] Decimal integer intent extras with leading zeros are passed to Android as octal #4156

Closed
opened 2026-10-31 00:47:15 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6807

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

CLI

Observed behavior

The shared start_adb_activity schema accepts int values 010, -010, and 08 as signed decimal text. The production argument builder forwards each string unchanged as the operand of Android's --ei option. Android's released parser uses Integer.decode, so these strings mean octal 8, octal -8, and a number-format error respectively, rather than decimal 10, -10, and 8.

Schema acceptance and argument construction were executed locally. The Android outcomes above are source-derived from the released parser and Java's documented conversion rules; no Android device, ADB process, Activity Manager, or receiving application was run.

Reproduction

From the recorded source checkout with locked dependencies installed, save this as probe.mts at the checkout root and run node --import tsx probe.mts:

import { adbInputSchemas } from './src/domain/adb/adbDeviceAnalysis.ts';
import { AdbProvider } from './src/adb/AdbProvider.ts';
import { adbArguments } from './src/adb/AdbCommand.ts';
for (const value of ['10', '010', '-010', '08']) {
  const input = adbInputSchemas.start_adb_activity.parse({
    serial: 'emulator-5554', action: 'android.intent.action.VIEW',
    extras: [{ key: 'count', type: 'int', value }]
  });
  const receiver = { runAmStart: async (...args: unknown[]) => {
    console.log(JSON.stringify({ input: value, accepted: true,
      arguments: adbArguments(input.serial,
        ['shell', 'am', 'start', '-W', ...(args[5] as string[])])
    }));
    return { ok: true, value: {} };
  }};
  await (AdbProvider.prototype as any).startActivity.call(receiver,
    'start_adb_activity', {}, {}, {}, input, undefined);
}

This is the executed production-builder probe with portable import locations. Its runAmStart sink records arguments instead of launching a process; it is not a full provider or transport reproduction. All four cases ran once before drafting. The ordinary 10 value is the control.

A corresponding public CLI trigger is rea start-adb-activity emulator-5554 android.intent.action.VIEW --extra int:count:010. That command was not run; observing a receiving activity's integer extra remains untested.

Expected behavior

Deliver the numeric value promised by REA's signed-decimal input contract: decimal 010 and 10 should both deliver integer 10. A supported decimal value containing 8 or 9 should not become invalid solely because it has a leading zero.

The integer-extra schema explicitly describes signed decimal text and accepts these strings.

Impact and scope

A caller supplying padded decimal integers can send a different value to the activity or encounter a launch failure. This is a bounded input-conversion defect, independent of the existing float-notation and empty-string reports. Its frequency in real workflows is unknown. Long, float, and string extras are outside this report.

Using canonical decimal text without redundant leading zeros avoids the source-derived radix mismatch; the 10 control reached the argument sink unchanged. The workaround was not exercised on an Android device.

REA version

Source main e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4, package manifest 6.7.0. Published release tag rea-agents-6.7.0 was inspected: its provider also accepts decimal-digit strings and forwards them unchanged, but its runtime was not executed.

Runtime and platform

Node.js v26.12.1; Linux x64; locked checkout dependencies. Android behavior is derived from Android 16 release source, rather than an attached device.

Target and artifact context

In-memory intent requests with one int extra named count; no target application or private data.

Interface

Other

Earliest failure stage

Transport or result projection

Relevant output or evidence

The recorded production-builder output contains these accepted final argument triples:

input=10    --ei count 10
input=010   --ei count 010
input=-010  --ei count -010
input=08    --ei count 08

The shared service validates the request and passes it to the provider. The provider builder selects --ei and preserves the raw value. In Android's released Intent parser, --ei calls decodeInteger; the conversion helper delegates to Integer.decode and has only a hexadecimal fallback. Java's Integer.decode contract specifies that a leading zero selects octal. These sources establish the downstream mismatch; it was not measured on a device.

Evidence provenance: observed schema/builder behavior plus static downstream proof. Local verification: reproduced argument forwarding; Android runtime not run. Reproduction completeness: complete for the builder, incomplete for an end-to-end activity observation. Missing fact: the extra read by a receiving Android activity in a live CLI/MCP run.

Typed outcome or recovery expected

Preserve the accepted decimal integer's numeric value across the REA-to-Android boundary. A restoration check should compare what the receiving activity obtains for 010, -010, 08, and the ordinary 10 control against decimal 10, -10, 8, and 10 respectively.

Analysis or suspected cause

Source-derived: REA's decimal contract and Android's radix-detecting operand syntax differ, and the argument builder performs no conversion between them.

Additional context

Open and closed searches covered start-adb-activity, adb octal, and leading zero. Related #6796 concerns rejected float scientific notation; #5093 concerns empty string rejection. Neither concerns the integer value delivered after acceptance. No last known good version established. Prepared with AI assistance.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Accepted padded decimal integer inputs cross a documented parser boundary with a different radix or become invalid; impact is bounded to these inputs, and no real-device frequency was measured.
  • Workaround status: unverified
  • Workaround basis: Canonical decimal strings avoid Android's leading-zero branch by source inspection and the control reaches the argument sink unchanged, but no receiving activity was executed.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6807 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area CLI ## Observed behavior The shared `start_adb_activity` schema accepts `int` values `010`, `-010`, and `08` as signed decimal text. The production argument builder forwards each string unchanged as the operand of Android's `--ei` option. Android's released parser uses `Integer.decode`, so these strings mean octal 8, octal -8, and a number-format error respectively, rather than decimal 10, -10, and 8. Schema acceptance and argument construction were executed locally. The Android outcomes above are source-derived from the released parser and Java's documented conversion rules; no Android device, ADB process, Activity Manager, or receiving application was run. ## Reproduction From the recorded source checkout with locked dependencies installed, save this as `probe.mts` at the checkout root and run `node --import tsx probe.mts`: ```ts import { adbInputSchemas } from './src/domain/adb/adbDeviceAnalysis.ts'; import { AdbProvider } from './src/adb/AdbProvider.ts'; import { adbArguments } from './src/adb/AdbCommand.ts'; for (const value of ['10', '010', '-010', '08']) { const input = adbInputSchemas.start_adb_activity.parse({ serial: 'emulator-5554', action: 'android.intent.action.VIEW', extras: [{ key: 'count', type: 'int', value }] }); const receiver = { runAmStart: async (...args: unknown[]) => { console.log(JSON.stringify({ input: value, accepted: true, arguments: adbArguments(input.serial, ['shell', 'am', 'start', '-W', ...(args[5] as string[])]) })); return { ok: true, value: {} }; }}; await (AdbProvider.prototype as any).startActivity.call(receiver, 'start_adb_activity', {}, {}, {}, input, undefined); } ``` This is the executed production-builder probe with portable import locations. Its `runAmStart` sink records arguments instead of launching a process; it is not a full provider or transport reproduction. All four cases ran once before drafting. The ordinary `10` value is the control. A corresponding public CLI trigger is `rea start-adb-activity emulator-5554 android.intent.action.VIEW --extra int:count:010`. That command was not run; observing a receiving activity's integer extra remains untested. ## Expected behavior Deliver the numeric value promised by REA's signed-decimal input contract: decimal `010` and `10` should both deliver integer 10. A supported decimal value containing 8 or 9 should not become invalid solely because it has a leading zero. The [integer-extra schema](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/domain/adb/adbDeviceAnalysis.ts#L77-L82) explicitly describes signed decimal text and accepts these strings. ## Impact and scope A caller supplying padded decimal integers can send a different value to the activity or encounter a launch failure. This is a bounded input-conversion defect, independent of the existing float-notation and empty-string reports. Its frequency in real workflows is unknown. Long, float, and string extras are outside this report. Using canonical decimal text without redundant leading zeros avoids the source-derived radix mismatch; the `10` control reached the argument sink unchanged. The workaround was not exercised on an Android device. ## REA version Source main `e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4`, package manifest 6.7.0. Published release tag `rea-agents-6.7.0` was inspected: its provider also accepts decimal-digit strings and forwards them unchanged, but its runtime was not executed. ## Runtime and platform Node.js v26.12.1; Linux x64; locked checkout dependencies. Android behavior is derived from Android 16 release source, rather than an attached device. ## Target and artifact context In-memory intent requests with one `int` extra named `count`; no target application or private data. ## Interface Other ## Earliest failure stage Transport or result projection ## Relevant output or evidence The recorded production-builder output contains these accepted final argument triples: ```text input=10 --ei count 10 input=010 --ei count 010 input=-010 --ei count -010 input=08 --ei count 08 ``` The [shared service](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/application/adb/AdbDeviceAnalysisService.ts#L19-L30) validates the request and passes it to the provider. The [provider builder](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/adb/AdbProvider.ts#L2811-L2827) selects `--ei` and preserves the raw value. In Android's [released Intent parser](https://github.com/aosp-mirror/platform_frameworks_base/blob/android-16.0.0_r1/core/java/android/content/Intent.java#L8684-L8688), `--ei` calls `decodeInteger`; the [conversion helper](https://github.com/aosp-mirror/platform_frameworks_base/blob/android-16.0.0_r1/core/java/android/content/Intent.java#L8605-L8620) delegates to `Integer.decode` and has only a hexadecimal fallback. Java's [Integer.decode contract](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Integer.html#decode(java.lang.String)) specifies that a leading zero selects octal. These sources establish the downstream mismatch; it was not measured on a device. Evidence provenance: observed schema/builder behavior plus static downstream proof. Local verification: reproduced argument forwarding; Android runtime not run. Reproduction completeness: complete for the builder, incomplete for an end-to-end activity observation. Missing fact: the extra read by a receiving Android activity in a live CLI/MCP run. ## Typed outcome or recovery expected Preserve the accepted decimal integer's numeric value across the REA-to-Android boundary. A restoration check should compare what the receiving activity obtains for `010`, `-010`, `08`, and the ordinary `10` control against decimal 10, -10, 8, and 10 respectively. ## Analysis or suspected cause Source-derived: REA's decimal contract and Android's radix-detecting operand syntax differ, and the argument builder performs no conversion between them. ## Additional context Open and closed searches covered `start-adb-activity`, `adb octal`, and `leading zero`. Related #6796 concerns rejected float scientific notation; #5093 concerns empty string rejection. Neither concerns the integer value delivered after acceptance. No last known good version established. Prepared with AI assistance. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Accepted padded decimal integer inputs cross a documented parser boundary with a different radix or become invalid; impact is bounded to these inputs, and no real-device frequency was measured. - Workaround status: unverified - Workaround basis: Canonical decimal strings avoid Android's leading-zero branch by source inspection and the control reaches the argument sink unchanged, but no receiving activity was executed.
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#4156
No description provided.