Validation.
This commit is contained in:
@@ -12,7 +12,9 @@ export function cloneBytes(data){ requireBytes(data); return new Uint8Array(data
|
||||
export function sliceBytes(data,offset,length){ assertRange(data,offset,length); return data.slice(offset,offset+length); }
|
||||
export function bytesToHex(data,separator=" "){ requireBytes(data); return Array.from(data,b=>b.toString(16).padStart(2,"0")).join(separator).toUpperCase(); }
|
||||
export function hexToBytes(text){
|
||||
const s=String(text).replace(/[^0-9a-f]/gi,"");
|
||||
const input=String(text);
|
||||
if(/[^0-9a-f\s,:-]/i.test(input)) throw new Error("Invalid character in hex text");
|
||||
const s=input.replace(/[\s,:-]/g,"");
|
||||
if(s.length%2) throw new Error("Hex text must contain complete bytes");
|
||||
const out=new Uint8Array(s.length/2); for(let i=0;i<out.length;i++) out[i]=parseInt(s.slice(i*2,i*2+2),16); return out;
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ export function verifyChecksumRegion(data, region, checksum, algorithm) {
|
||||
assertRange(data, region.start, region.length);
|
||||
assertRange(data, checksum.offset, checksum.length);
|
||||
if (![1, 2, 4].includes(checksum.length)) throw new RangeError("Checksum length must be 1, 2, or 4 bytes");
|
||||
const endian = checksum.endian || "LE";
|
||||
if (endian !== "LE" && endian !== "BE") throw new RangeError("Checksum endian must be LE or BE");
|
||||
const computed = algorithm(data.slice(region.start, region.start + region.length)) >>> 0;
|
||||
let stored = 0;
|
||||
for (let index = 0; index < checksum.length; index++) {
|
||||
const shift = checksum.endian === "BE" ? 8 * (checksum.length - index - 1) : 8 * index;
|
||||
const shift = endian === "BE" ? 8 * (checksum.length - index - 1) : 8 * index;
|
||||
stored = (stored | (data[checksum.offset + index] << shift)) >>> 0;
|
||||
}
|
||||
const mask = checksum.length === 4 ? 0xFFFFFFFF : (2 ** (checksum.length * 8)) - 1;
|
||||
return {
|
||||
region: { start: region.start, length: region.length },
|
||||
checksum: { offset: checksum.offset, length: checksum.length, endian: checksum.endian || "LE" },
|
||||
checksum: { offset: checksum.offset, length: checksum.length, endian },
|
||||
stored: stored & mask,
|
||||
computed: computed & mask,
|
||||
matches: (stored & mask) === (computed & mask)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { strict as assert } from "node:assert";
|
||||
import { adler32 } from "../binary_utils.mjs";
|
||||
import { adler32, hexToBytes } from "../binary_utils.mjs";
|
||||
import { verifyChecksumRegion } from "../templates/checksum_region_verifier.mjs";
|
||||
import { fingerprintDump } from "../examples/32_dump_fingerprint.mjs";
|
||||
import { buildChangeReport } from "../examples/33_structured_change_report.mjs";
|
||||
@@ -11,6 +11,9 @@ new DataView(withChecksum.buffer).setUint32(4, adler32(payload), false);
|
||||
assert.equal(verifyChecksumRegion(withChecksum, { start: 0, length: 4 }, { offset: 4, length: 4, endian: "BE" }, adler32).matches, true);
|
||||
withChecksum[0] = 9;
|
||||
assert.equal(verifyChecksumRegion(withChecksum, { start: 0, length: 4 }, { offset: 4, length: 4, endian: "BE" }, adler32).matches, false);
|
||||
assert.deepEqual(hexToBytes("00:0f ff"), new Uint8Array([0, 15, 255]));
|
||||
assert.throws(() => hexToBytes("12zz34"), /Invalid character/);
|
||||
assert.throws(() => verifyChecksumRegion(withChecksum, { start: 0, length: 4 }, { offset: 4, length: 4, endian: "BIG" }, adler32), /endian must be LE or BE/);
|
||||
|
||||
const fingerprint = fingerprintDump(payload, "fixture.bin");
|
||||
assert.equal(fingerprint.length, 4);
|
||||
|
||||
+5
-5
@@ -64,7 +64,7 @@ Support legitimate, authorized automotive shop operations and educational resear
|
||||
- Submit a pull request with a clear description
|
||||
|
||||
### 4. Contribute Safe Examples
|
||||
- Base on the [03_Script_Starter_Kit/](../03_Script_Starter_Kit/) templates
|
||||
- Base on the [03_Script_Starter_Kit/](03_Script_Starter_Kit/) templates
|
||||
- Include detailed comments explaining the script's purpose
|
||||
- Add test cases or validation examples
|
||||
- Document assumptions and dependencies
|
||||
@@ -73,7 +73,7 @@ Support legitimate, authorized automotive shop operations and educational resear
|
||||
- Preserve all source attribution
|
||||
|
||||
### 5. Contribute Tests
|
||||
- Add to [16_Tests/](../16_Tests/) directory
|
||||
- Add to [16_Tests/](16_Tests/) directory
|
||||
- Use synthetic, non-confidential test data
|
||||
- Document test purpose and coverage
|
||||
- Include expected results
|
||||
@@ -134,12 +134,12 @@ If you discover a security vulnerability or suspicious content:
|
||||
4. **Allow time** for response and remediation
|
||||
5. **Do not share** the vulnerability publicly until patched
|
||||
|
||||
See [SECURITY.md](../SECURITY.md) for full details.
|
||||
See [SECURITY.md](SECURITY.md) for full details.
|
||||
|
||||
## Questions?
|
||||
|
||||
- Check existing [documentation](../01_Knowledge_Base/)
|
||||
- Review [SECURITY.md](../SECURITY.md) and [LICENSES.md](../LICENSES.md)
|
||||
- Check existing [documentation](01_Knowledge_Base/)
|
||||
- Review [SECURITY.md](SECURITY.md) and [LICENSES.md](LICENSES.md)
|
||||
- Open a discussion or issue if unclear
|
||||
- Be patient and respectful in all interactions
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
sd# XHorse Multi-PROG Ultimate Kit
|
||||
# XHorse Multi-PROG Ultimate Kit
|
||||
|
||||
A comprehensive, auditable knowledge base and development toolkit for safe, authorized XHorse Multi-PROG scripting and ECU/immobilizer module repair operations.
|
||||
|
||||
|
||||
+19
-16
@@ -3,10 +3,15 @@
|
||||
# Generated: 2026-09-04
|
||||
|
||||
param(
|
||||
[string]$RepositoryRoot = "\\unas\Workspace\CDiag\Scripts\XHorse_MultiPROG_Ultimate_Kit",
|
||||
[string]$OutputDir = "$RepositoryRoot\14_Repository_Review"
|
||||
[string]$RepositoryRoot = (Join-Path $PSScriptRoot ".."),
|
||||
[string]$OutputDir
|
||||
)
|
||||
|
||||
$RepositoryRoot = (Resolve-Path -LiteralPath $RepositoryRoot).Path
|
||||
if ([string]::IsNullOrWhiteSpace($OutputDir)) {
|
||||
$OutputDir = Join-Path $RepositoryRoot "14_Repository_Review"
|
||||
}
|
||||
|
||||
$problems = @{
|
||||
EmptyFiles = @()
|
||||
UnknownFileTypes = @()
|
||||
@@ -154,7 +159,6 @@ Write-Host " Found $suspiciousCount files with suspicious patterns"
|
||||
# 6. Hash-based duplicate detection
|
||||
Write-Host "Detecting duplicate files by content..."
|
||||
$hashMap = @{}
|
||||
$duplicates = @()
|
||||
|
||||
foreach ($file in $files) {
|
||||
if ($file.Length -gt 0) {
|
||||
@@ -165,9 +169,9 @@ foreach ($file in $files) {
|
||||
$stream.Close()
|
||||
|
||||
if ($hashMap.ContainsKey($sha256)) {
|
||||
$duplicates += @($hashMap[$sha256], $file.FullName)
|
||||
$hashMap[$sha256] += $file.FullName
|
||||
} else {
|
||||
$hashMap[$sha256] = $file.FullName
|
||||
$hashMap[$sha256] = @($file.FullName)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
@@ -177,23 +181,22 @@ foreach ($file in $files) {
|
||||
}
|
||||
|
||||
$groupedDuplicates = @{}
|
||||
foreach ($dup in $duplicates) {
|
||||
$relPath = $dup.Substring($RepositoryRoot.Length + 1)
|
||||
$hash = (Get-FileHash -Path $dup -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
|
||||
if (-not $groupedDuplicates.ContainsKey($hash)) {
|
||||
$groupedDuplicates[$hash] = @()
|
||||
foreach ($hash in $hashMap.Keys) {
|
||||
if ($hashMap[$hash].Count -gt 1) {
|
||||
$groupedDuplicates[$hash] = @($hashMap[$hash] | ForEach-Object {
|
||||
$_.Substring($RepositoryRoot.Length + 1)
|
||||
})
|
||||
}
|
||||
$groupedDuplicates[$hash] += $relPath
|
||||
}
|
||||
|
||||
Write-Host " Found $($groupedDuplicates.Count) groups of duplicate files"
|
||||
foreach ($hash in $groupedDuplicates.Keys) {
|
||||
$files = $groupedDuplicates[$hash]
|
||||
if ($files.Count -gt 1) {
|
||||
$duplicatePaths = $groupedDuplicates[$hash]
|
||||
if ($duplicatePaths.Count -gt 1) {
|
||||
$problems.DuplicatesByHash += @{
|
||||
SHA256 = $hash
|
||||
Count = $files.Count
|
||||
Files = $files
|
||||
Count = $duplicatePaths.Count
|
||||
Files = $duplicatePaths
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,7 +226,7 @@ if ($problems.LargeFiles.Count -gt 0) {
|
||||
|
||||
$reportPath = Join-Path $OutputDir "suspicious_files.csv"
|
||||
if ($problems.SuspiciousFiles.Count -gt 0) {
|
||||
$problems.SuspiciousFiles | ConvertTo-Csv -NoTypeInformation | Set-Content -Path $reportPath -Encoding UTF8 -Force
|
||||
$problems.SuspiciousFiles | ForEach-Object { [PSCustomObject]$_ } | ConvertTo-Csv -NoTypeInformation | Set-Content -Path $reportPath -Encoding UTF8 -Force
|
||||
Write-Host " Exported: suspicious_files.csv ($($problems.SuspiciousFiles.Count) files)"
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
# Generated: 2026-09-04
|
||||
|
||||
param(
|
||||
[string]$RepositoryRoot = "\\unas\Workspace\CDiag\Scripts\XHorse_MultiPROG_Ultimate_Kit",
|
||||
[string]$OutputDir = "$RepositoryRoot\14_Repository_Review"
|
||||
[string]$RepositoryRoot = (Join-Path $PSScriptRoot ".."),
|
||||
[string]$OutputDir
|
||||
)
|
||||
|
||||
$RepositoryRoot = (Resolve-Path -LiteralPath $RepositoryRoot).Path
|
||||
if ([string]::IsNullOrWhiteSpace($OutputDir)) {
|
||||
$OutputDir = Join-Path $RepositoryRoot "14_Repository_Review"
|
||||
}
|
||||
|
||||
function Get-FileCategory {
|
||||
param([string]$Extension)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user