fix(pcap): order evidence ties by code point instead of host locale (#2509)
The pcap summary sorted equal-count endpoints and protocol stacks with String#localeCompare, and Flutter build inspection sorted APK ABI directory names the same way. localeCompare follows the host's ICU locale, so the same capture produced differently ordered Evidence on different hosts: under da_DK "aarp" sorts after "zz", under lt_LT "syslog" sorts before "ssdp", and every locale puts "fe80::1" before "fe80:1::1". Use the repository's compareUnicodeCodePoints, as the other Evidence producers already do. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d73ed6fce2
commit
f6556ad2bc
|
|
@ -23,6 +23,7 @@ import {
|
|||
AnalysisUnsupportedTargetError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { AnalysisProtocolError } from "../domain/analysisErrorCore.js";
|
||||
import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
|
||||
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import {
|
||||
|
|
@ -759,7 +760,7 @@ export class FlutterBuildProvider {
|
|||
toolchain_capped: value.libflutter.toolchainCapped,
|
||||
},
|
||||
}))
|
||||
.sort((left, right) => left.abi.localeCompare(right.abi));
|
||||
.sort((left, right) => compareUnicodeCodePoints(left.abi, right.abi));
|
||||
const flutterDetected = abis.some((entry) => entry.libapp.present);
|
||||
const partial =
|
||||
abis.some(
|
||||
|
|
@ -871,7 +872,7 @@ export class FlutterBuildProvider {
|
|||
(left, right) =>
|
||||
(preference.indexOf(left.abi) + 1 || preference.length + 1) -
|
||||
(preference.indexOf(right.abi) + 1 || preference.length + 1) ||
|
||||
left.abi.localeCompare(right.abi),
|
||||
compareUnicodeCodePoints(left.abi, right.abi),
|
||||
)[0]!
|
||||
: candidates.find((candidate) => candidate.abi === abi);
|
||||
if (selected === undefined)
|
||||
|
|
|
|||
|
|
@ -83,6 +83,24 @@ it("counts IPv6 endpoints once per packet and preserves every examined fact", as
|
|||
expect(result.partial).toBe(false);
|
||||
});
|
||||
|
||||
it("orders equal-count endpoints and protocols by code point, not host locale", async () => {
|
||||
// Locale collation puts "fe80::1" first and, under da-DK, "aarp" after "zz".
|
||||
const result = await parseTsharkJsonOutput(
|
||||
capture([
|
||||
{ "ipv6.src": ["fe80::1"], "frame.protocols": ["eth:llc:zz"] },
|
||||
{ "ipv6.src": ["fe80:1::1"], "frame.protocols": ["eth:llc:aarp"] },
|
||||
]),
|
||||
);
|
||||
expect(result.endpoints.map(({ address }) => address)).toEqual([
|
||||
"fe80:1::1",
|
||||
"fe80::1",
|
||||
]);
|
||||
expect(result.protocolDistribution.map(({ protocol }) => protocol)).toEqual([
|
||||
"eth:llc:aarp",
|
||||
"eth:llc:zz",
|
||||
]);
|
||||
});
|
||||
|
||||
it("preserves all DNS addresses and their exact examined count", async () => {
|
||||
const result = await parseTsharkJsonOutput(
|
||||
capture(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
AnalysisResourceConstraintError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { parseRecordedTransportUrl } from "../domain/recordedTransportUrl.js";
|
||||
import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
|
||||
|
||||
const OPERATION = "inspect_pcap_capture";
|
||||
/** Bounds JSON decoding plus its expanded object graph before JSON.parse. */
|
||||
|
|
@ -284,7 +285,7 @@ export const parseTsharkJsonOutput = async (
|
|||
signal?.throwIfAborted();
|
||||
return {
|
||||
endpoints: [...endpoints]
|
||||
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
||||
.sort((a, b) => b[1] - a[1] || compareUnicodeCodePoints(a[0], b[0]))
|
||||
.map(([address, packet_count]) => ({
|
||||
address,
|
||||
port: null,
|
||||
|
|
@ -300,7 +301,7 @@ export const parseTsharkJsonOutput = async (
|
|||
tlsSniValues: [...sni],
|
||||
tlsSniCount: sni.size,
|
||||
protocolDistribution: [...protocols]
|
||||
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
||||
.sort((a, b) => b[1] - a[1] || compareUnicodeCodePoints(a[0], b[0]))
|
||||
.map(([protocol, packet_count]) => ({ protocol, packet_count })),
|
||||
protocolCount: protocols.size,
|
||||
httpRequestUris: [...uris],
|
||||
|
|
|
|||
Loading…
Reference in New Issue